Coverage Report

Created: 2026-02-14 07:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/gimli-0.32.3/src/read/aranges.rs
Line
Count
Source
1
use crate::common::{DebugArangesOffset, DebugInfoOffset, Encoding, SectionId};
2
use crate::endianity::Endianity;
3
use crate::read::{
4
    EndianSlice, Error, Range, Reader, ReaderAddress, ReaderOffset, Result, Section,
5
};
6
7
/// The `DebugAranges` struct represents the DWARF address range information
8
/// found in the `.debug_aranges` section.
9
#[derive(Debug, Default, Clone, Copy)]
10
pub struct DebugAranges<R> {
11
    section: R,
12
}
13
14
impl<'input, Endian> DebugAranges<EndianSlice<'input, Endian>>
15
where
16
    Endian: Endianity,
17
{
18
    /// Construct a new `DebugAranges` instance from the data in the `.debug_aranges`
19
    /// section.
20
    ///
21
    /// It is the caller's responsibility to read the `.debug_aranges` section and
22
    /// present it as a `&[u8]` slice. That means using some ELF loader on
23
    /// Linux, a Mach-O loader on macOS, etc.
24
    ///
25
    /// ```
26
    /// use gimli::{DebugAranges, LittleEndian};
27
    ///
28
    /// # let buf = [];
29
    /// # let read_debug_aranges_section = || &buf;
30
    /// let debug_aranges =
31
    ///     DebugAranges::new(read_debug_aranges_section(), LittleEndian);
32
    /// ```
33
0
    pub fn new(section: &'input [u8], endian: Endian) -> Self {
34
0
        DebugAranges {
35
0
            section: EndianSlice::new(section, endian),
36
0
        }
37
0
    }
38
}
39
40
impl<R: Reader> DebugAranges<R> {
41
    /// Iterate the sets of entries in the `.debug_aranges` section.
42
    ///
43
    /// Each set of entries belongs to a single unit.
44
0
    pub fn headers(&self) -> ArangeHeaderIter<R> {
45
0
        ArangeHeaderIter {
46
0
            input: self.section.clone(),
47
0
            offset: DebugArangesOffset(R::Offset::from_u8(0)),
48
0
        }
49
0
    }
Unexecuted instantiation: <gimli::read::aranges::DebugAranges<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::headers
Unexecuted instantiation: <gimli::read::aranges::DebugAranges<_>>::headers
50
51
    /// Get the header at the given offset.
52
0
    pub fn header(&self, offset: DebugArangesOffset<R::Offset>) -> Result<ArangeHeader<R>> {
53
0
        let mut input = self.section.clone();
54
0
        input.skip(offset.0)?;
55
0
        ArangeHeader::parse(&mut input, offset)
56
0
    }
Unexecuted instantiation: <gimli::read::aranges::DebugAranges<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::header
Unexecuted instantiation: <gimli::read::aranges::DebugAranges<_>>::header
57
}
58
59
impl<T> DebugAranges<T> {
60
    /// Create a `DebugAranges` section that references the data in `self`.
61
    ///
62
    /// This is useful when `R` implements `Reader` but `T` does not.
63
    ///
64
    /// Used by `DwarfSections::borrow`.
65
0
    pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAranges<R>
66
0
    where
67
0
        F: FnMut(&'a T) -> R,
68
    {
69
0
        borrow(&self.section).into()
70
0
    }
71
}
72
73
impl<R> Section<R> for DebugAranges<R> {
74
0
    fn id() -> SectionId {
75
0
        SectionId::DebugAranges
76
0
    }
Unexecuted instantiation: <gimli::read::aranges::DebugAranges<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>> as gimli::read::Section<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::id
Unexecuted instantiation: <gimli::read::aranges::DebugAranges<_> as gimli::read::Section<_>>::id
77
78
0
    fn reader(&self) -> &R {
79
0
        &self.section
80
0
    }
81
}
82
83
impl<R> From<R> for DebugAranges<R> {
84
0
    fn from(section: R) -> Self {
85
0
        DebugAranges { section }
86
0
    }
Unexecuted instantiation: <gimli::read::aranges::DebugAranges<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>> as core::convert::From<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::from
Unexecuted instantiation: <gimli::read::aranges::DebugAranges<_> as core::convert::From<_>>::from
87
}
88
89
/// An iterator over the headers of a `.debug_aranges` section.
90
#[derive(Clone, Debug)]
91
pub struct ArangeHeaderIter<R: Reader> {
92
    input: R,
93
    offset: DebugArangesOffset<R::Offset>,
94
}
95
96
impl<R: Reader> ArangeHeaderIter<R> {
97
    /// Advance the iterator to the next header.
98
0
    pub fn next(&mut self) -> Result<Option<ArangeHeader<R>>> {
99
0
        if self.input.is_empty() {
100
0
            return Ok(None);
101
0
        }
102
103
0
        let len = self.input.len();
104
0
        match ArangeHeader::parse(&mut self.input, self.offset) {
105
0
            Ok(header) => {
106
0
                self.offset.0 += len - self.input.len();
107
0
                Ok(Some(header))
108
            }
109
0
            Err(e) => {
110
0
                self.input.empty();
111
0
                Err(e)
112
            }
113
        }
114
0
    }
Unexecuted instantiation: <gimli::read::aranges::ArangeHeaderIter<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::next
Unexecuted instantiation: <gimli::read::aranges::ArangeHeaderIter<_>>::next
115
}
116
117
#[cfg(feature = "fallible-iterator")]
118
impl<R: Reader> fallible_iterator::FallibleIterator for ArangeHeaderIter<R> {
119
    type Item = ArangeHeader<R>;
120
    type Error = Error;
121
122
0
    fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
123
0
        ArangeHeaderIter::next(self)
124
0
    }
125
}
126
127
/// A header for a set of entries in the `.debug_arange` section.
128
///
129
/// These entries all belong to a single unit.
130
#[derive(Debug, Clone, PartialEq, Eq)]
131
pub struct ArangeHeader<R, Offset = <R as Reader>::Offset>
132
where
133
    R: Reader<Offset = Offset>,
134
    Offset: ReaderOffset,
135
{
136
    offset: DebugArangesOffset<Offset>,
137
    encoding: Encoding,
138
    length: Offset,
139
    debug_info_offset: DebugInfoOffset<Offset>,
140
    entries: R,
141
}
142
143
impl<R, Offset> ArangeHeader<R, Offset>
144
where
145
    R: Reader<Offset = Offset>,
146
    Offset: ReaderOffset,
147
{
148
0
    fn parse(input: &mut R, offset: DebugArangesOffset<Offset>) -> Result<Self> {
149
0
        let (length, format) = input.read_initial_length()?;
150
0
        let mut rest = input.split(length)?;
151
152
        // Check the version. The DWARF 5 spec says that this is always 2, but version 3
153
        // has been observed in the wild, potentially due to a bug; see
154
        // https://github.com/gimli-rs/gimli/issues/559 for more information.
155
        // lldb allows versions 2 through 5, possibly by mistake.
156
0
        let version = rest.read_u16()?;
157
0
        if version != 2 && version != 3 {
158
0
            return Err(Error::UnknownVersion(u64::from(version)));
159
0
        }
160
161
0
        let debug_info_offset = rest.read_offset(format).map(DebugInfoOffset)?;
162
0
        let address_size = rest.read_address_size()?;
163
0
        let segment_size = rest.read_u8()?;
164
0
        if segment_size != 0 {
165
0
            return Err(Error::UnsupportedSegmentSize);
166
0
        }
167
168
        // unit_length + version + offset + address_size + segment_size
169
0
        let header_length = format.initial_length_size() + 2 + format.word_size() + 1 + 1;
170
171
        // The first tuple following the header in each set begins at an offset that is
172
        // a multiple of the size of a single tuple (that is, twice the size of an address).
173
0
        let tuple_length = address_size
174
0
            .checked_mul(2)
175
0
            .ok_or(Error::UnsupportedAddressSize(address_size))?;
176
0
        if tuple_length == 0 {
177
0
            return Err(Error::UnsupportedAddressSize(address_size));
178
0
        }
179
0
        let padding = if header_length % tuple_length == 0 {
180
0
            0
181
        } else {
182
0
            tuple_length - header_length % tuple_length
183
        };
184
0
        rest.skip(R::Offset::from_u8(padding))?;
185
186
0
        let encoding = Encoding {
187
0
            format,
188
0
            version,
189
0
            address_size,
190
0
        };
191
0
        Ok(ArangeHeader {
192
0
            offset,
193
0
            encoding,
194
0
            length,
195
0
            debug_info_offset,
196
0
            entries: rest,
197
0
        })
198
0
    }
Unexecuted instantiation: <gimli::read::aranges::ArangeHeader<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>, usize>>::parse
Unexecuted instantiation: <gimli::read::aranges::ArangeHeader<_, _>>::parse
199
200
    /// Return the offset of this header within the `.debug_aranges` section.
201
    #[inline]
202
0
    pub fn offset(&self) -> DebugArangesOffset<Offset> {
203
0
        self.offset
204
0
    }
Unexecuted instantiation: <gimli::read::aranges::ArangeHeader<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>, usize>>::offset
Unexecuted instantiation: <gimli::read::aranges::ArangeHeader<_, _>>::offset
205
206
    /// Return the length of this set of entries, including the header.
207
    #[inline]
208
0
    pub fn length(&self) -> Offset {
209
0
        self.length
210
0
    }
211
212
    /// Return the encoding parameters for this set of entries.
213
    #[inline]
214
0
    pub fn encoding(&self) -> Encoding {
215
0
        self.encoding
216
0
    }
217
218
    /// Return the offset into the .debug_info section for this set of arange entries.
219
    #[inline]
220
0
    pub fn debug_info_offset(&self) -> DebugInfoOffset<Offset> {
221
0
        self.debug_info_offset
222
0
    }
Unexecuted instantiation: <gimli::read::aranges::ArangeHeader<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>, usize>>::debug_info_offset
Unexecuted instantiation: <gimli::read::aranges::ArangeHeader<_, _>>::debug_info_offset
223
224
    /// Return the arange entries in this set.
225
    #[inline]
226
0
    pub fn entries(&self) -> ArangeEntryIter<R> {
227
0
        ArangeEntryIter {
228
0
            input: self.entries.clone(),
229
0
            encoding: self.encoding,
230
0
        }
231
0
    }
Unexecuted instantiation: <gimli::read::aranges::ArangeHeader<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>, usize>>::entries
Unexecuted instantiation: <gimli::read::aranges::ArangeHeader<_, _>>::entries
232
}
233
234
/// An iterator over the aranges from a `.debug_aranges` section.
235
///
236
/// Can be [used with
237
/// `FallibleIterator`](./index.html#using-with-fallibleiterator).
238
#[derive(Debug, Clone)]
239
pub struct ArangeEntryIter<R: Reader> {
240
    input: R,
241
    encoding: Encoding,
242
}
243
244
impl<R: Reader> ArangeEntryIter<R> {
245
    /// Advance the iterator and return the next arange.
246
    ///
247
    /// Returns the newly parsed arange as `Ok(Some(arange))`. Returns `Ok(None)`
248
    /// when iteration is complete and all aranges have already been parsed and
249
    /// yielded. If an error occurs while parsing the next arange, then this error
250
    /// is returned as `Err(e)`, and all subsequent calls return `Ok(None)`.
251
0
    pub fn next(&mut self) -> Result<Option<ArangeEntry>> {
252
        loop {
253
0
            let raw_entry = match self.next_raw()? {
254
0
                Some(entry) => entry,
255
0
                None => return Ok(None),
256
            };
257
258
0
            let entry = self.convert_raw(raw_entry)?;
259
0
            if entry.is_some() {
260
0
                return Ok(entry);
261
0
            }
262
        }
263
0
    }
Unexecuted instantiation: <gimli::read::aranges::ArangeEntryIter<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::next
Unexecuted instantiation: <gimli::read::aranges::ArangeEntryIter<_>>::next
264
265
    /// Advance the iterator and return the next arange without validating it.
266
    ///
267
    /// The returned entry will have `range.end` set to 0.
268
    /// This will return tombstone entries as well.
269
0
    pub fn next_raw(&mut self) -> Result<Option<ArangeEntry>> {
270
0
        if self.input.is_empty() {
271
0
            return Ok(None);
272
0
        }
273
274
0
        match ArangeEntry::parse(&mut self.input, self.encoding) {
275
0
            Ok(Some(entry)) => Ok(Some(entry)),
276
            Ok(None) => {
277
0
                self.input.empty();
278
0
                Ok(None)
279
            }
280
0
            Err(e) => {
281
0
                self.input.empty();
282
0
                Err(e)
283
            }
284
        }
285
0
    }
Unexecuted instantiation: <gimli::read::aranges::ArangeEntryIter<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::next_raw
Unexecuted instantiation: <gimli::read::aranges::ArangeEntryIter<_>>::next_raw
286
287
    /// Convert a raw range into a range.
288
    ///
289
    /// The raw range should have been obtained from `next_raw`.
290
    #[doc(hidden)]
291
0
    pub fn convert_raw(&self, mut entry: ArangeEntry) -> Result<Option<ArangeEntry>> {
292
        // Skip negative tombstone entries.
293
        // Callers must handle tombstones of 0 or greater themselves
294
        // because we have no way of knowing if they are valid or not.
295
0
        let address_size = self.encoding.address_size;
296
0
        if entry.range.begin >= u64::min_tombstone(address_size) {
297
0
            return Ok(None);
298
0
        }
299
300
        // Calculate end now so that we can handle overflow.
301
0
        entry.range.end = entry.range.begin.add_sized(entry.length, address_size)?;
302
0
        Ok(Some(entry))
303
0
    }
Unexecuted instantiation: <gimli::read::aranges::ArangeEntryIter<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::convert_raw
Unexecuted instantiation: <gimli::read::aranges::ArangeEntryIter<_>>::convert_raw
304
}
305
306
#[cfg(feature = "fallible-iterator")]
307
impl<R: Reader> fallible_iterator::FallibleIterator for ArangeEntryIter<R> {
308
    type Item = ArangeEntry;
309
    type Error = Error;
310
311
0
    fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
312
0
        ArangeEntryIter::next(self)
313
0
    }
314
}
315
316
/// A single parsed arange.
317
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
318
pub struct ArangeEntry {
319
    range: Range,
320
    length: u64,
321
}
322
323
impl ArangeEntry {
324
    /// Parse a single arange. Return `None` for the null arange, `Some` for an actual arange.
325
0
    fn parse<R: Reader>(input: &mut R, encoding: Encoding) -> Result<Option<Self>> {
326
0
        let address_size = encoding.address_size;
327
328
0
        let tuple_length = R::Offset::from_u8(2 * address_size);
329
0
        if tuple_length > input.len() {
330
0
            input.empty();
331
0
            return Ok(None);
332
0
        }
333
334
0
        let begin = input.read_address(address_size)?;
335
0
        let length = input.read_address(address_size)?;
336
0
        let range = Range { begin, end: 0 };
337
338
0
        match (begin, length) {
339
            // This is meant to be a null terminator, but in practice it can occur
340
            // before the end, possibly due to a linker omitting a function and
341
            // leaving an unrelocated entry.
342
0
            (0, 0) => Self::parse(input, encoding),
343
0
            _ => Ok(Some(ArangeEntry { range, length })),
344
        }
345
0
    }
Unexecuted instantiation: <gimli::read::aranges::ArangeEntry>::parse::<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>
Unexecuted instantiation: <gimli::read::aranges::ArangeEntry>::parse::<_>
346
347
    /// Return the beginning address of this arange.
348
    #[inline]
349
0
    pub fn address(&self) -> u64 {
350
0
        self.range.begin
351
0
    }
352
353
    /// Return the length of this arange.
354
    #[inline]
355
0
    pub fn length(&self) -> u64 {
356
0
        self.length
357
0
    }
358
359
    /// Return the range.
360
    #[inline]
361
0
    pub fn range(&self) -> Range {
362
0
        self.range
363
0
    }
364
}
365
366
#[cfg(test)]
367
mod tests {
368
    use super::*;
369
    use crate::common::{DebugInfoOffset, Format};
370
    use crate::endianity::LittleEndian;
371
    use crate::read::EndianSlice;
372
373
    #[test]
374
    fn test_iterate_headers() {
375
        #[rustfmt::skip]
376
        let buf = [
377
            // 32-bit length = 28.
378
            0x1c, 0x00, 0x00, 0x00,
379
            // Version.
380
            0x02, 0x00,
381
            // Offset.
382
            0x01, 0x02, 0x03, 0x04,
383
            // Address size.
384
            0x04,
385
            // Segment size.
386
            0x00,
387
            // Dummy padding and arange tuples.
388
            0x00, 0x00, 0x00, 0x00,
389
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
390
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
391
392
            // 32-bit length = 36.
393
            0x24, 0x00, 0x00, 0x00,
394
            // Version.
395
            0x02, 0x00,
396
            // Offset.
397
            0x11, 0x12, 0x13, 0x14,
398
            // Address size.
399
            0x04,
400
            // Segment size.
401
            0x00,
402
            // Dummy padding and arange tuples.
403
            0x00, 0x00, 0x00, 0x00,
404
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
405
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
406
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
407
        ];
408
409
        let debug_aranges = DebugAranges::new(&buf, LittleEndian);
410
        let mut headers = debug_aranges.headers();
411
412
        let header = headers
413
            .next()
414
            .expect("should parse header ok")
415
            .expect("should have a header");
416
        assert_eq!(header.offset(), DebugArangesOffset(0));
417
        assert_eq!(header.debug_info_offset(), DebugInfoOffset(0x0403_0201));
418
419
        let header = headers
420
            .next()
421
            .expect("should parse header ok")
422
            .expect("should have a header");
423
        assert_eq!(header.offset(), DebugArangesOffset(0x20));
424
        assert_eq!(header.debug_info_offset(), DebugInfoOffset(0x1413_1211));
425
    }
426
427
    #[test]
428
    fn test_parse_header_ok() {
429
        #[rustfmt::skip]
430
        let buf = [
431
            // 32-bit length = 28 (8 bytes header, 4 bytes padding, 16 bytes tuple data).
432
            0x1c, 0x00, 0x00, 0x00,
433
            // Version.
434
            0x02, 0x00,
435
            // Offset.
436
            0x01, 0x02, 0x03, 0x04,
437
            // Address size.
438
            0x08,
439
            // Segment size.
440
            0x00,
441
            // Length to here = 12, tuple length = 16.
442
            // Padding to tuple length multiple = 4.
443
            0x10, 0x00, 0x00, 0x00,
444
445
            // Dummy arange tuple data.
446
            0x20, 0x00, 0x00, 0x00,
447
            0x00, 0x00, 0x00, 0x00,
448
            0x00, 0x00, 0x00, 0x00,
449
            0x00, 0x00, 0x00, 0x00,
450
451
            // Dummy next arange.
452
            0x30, 0x00, 0x00, 0x00,
453
            0x00, 0x00, 0x00, 0x00,
454
            0x00, 0x00, 0x00, 0x00,
455
            0x00, 0x00, 0x00, 0x00,
456
        ];
457
458
        let rest = &mut EndianSlice::new(&buf, LittleEndian);
459
460
        let header =
461
            ArangeHeader::parse(rest, DebugArangesOffset(0x10)).expect("should parse header ok");
462
463
        assert_eq!(
464
            *rest,
465
            EndianSlice::new(&buf[buf.len() - 16..], LittleEndian)
466
        );
467
        assert_eq!(
468
            header,
469
            ArangeHeader {
470
                offset: DebugArangesOffset(0x10),
471
                encoding: Encoding {
472
                    format: Format::Dwarf32,
473
                    version: 2,
474
                    address_size: 8,
475
                },
476
                length: 0x1c,
477
                debug_info_offset: DebugInfoOffset(0x0403_0201),
478
                entries: EndianSlice::new(&buf[buf.len() - 32..buf.len() - 16], LittleEndian),
479
            }
480
        );
481
    }
482
483
    #[test]
484
    fn test_parse_header_overflow_error() {
485
        #[rustfmt::skip]
486
        let buf = [
487
            // 32-bit length = 32.
488
            0x20, 0x00, 0x00, 0x00,
489
            // Version.
490
            0x02, 0x00,
491
            // Offset.
492
            0x01, 0x02, 0x03, 0x04,
493
            // Address size.
494
            0xff,
495
            // Segment size.
496
            0x00,
497
            // Length to here = 12, tuple length = 20.
498
            // Padding to tuple length multiple = 4.
499
            0x10, 0x00, 0x00, 0x00,
500
            0x00, 0x00, 0x00, 0x00,
501
502
            // Dummy arange tuple data.
503
            0x20, 0x00, 0x00, 0x00,
504
            0x00, 0x00, 0x00, 0x00,
505
            0x00, 0x00, 0x00, 0x00,
506
            0x00, 0x00, 0x00, 0x00,
507
508
            // Dummy next arange.
509
            0x30, 0x00, 0x00, 0x00,
510
            0x00, 0x00, 0x00, 0x00,
511
            0x00, 0x00, 0x00, 0x00,
512
            0x00, 0x00, 0x00, 0x00,
513
        ];
514
515
        let rest = &mut EndianSlice::new(&buf, LittleEndian);
516
517
        let error = ArangeHeader::parse(rest, DebugArangesOffset(0x10))
518
            .expect_err("should fail to parse header");
519
        assert_eq!(error, Error::UnsupportedAddressSize(0xff));
520
    }
521
522
    #[test]
523
    fn test_parse_header_div_by_zero_error() {
524
        #[rustfmt::skip]
525
        let buf = [
526
            // 32-bit length = 32.
527
            0x20, 0x00, 0x00, 0x00,
528
            // Version.
529
            0x02, 0x00,
530
            // Offset.
531
            0x01, 0x02, 0x03, 0x04,
532
            // Address size = 0. Could cause a division by zero if we aren't
533
            // careful.
534
            0x00,
535
            // Segment size.
536
            0x00,
537
            // Length to here = 12, tuple length = 20.
538
            // Padding to tuple length multiple = 4.
539
            0x10, 0x00, 0x00, 0x00,
540
            0x00, 0x00, 0x00, 0x00,
541
542
            // Dummy arange tuple data.
543
            0x20, 0x00, 0x00, 0x00,
544
            0x00, 0x00, 0x00, 0x00,
545
            0x00, 0x00, 0x00, 0x00,
546
            0x00, 0x00, 0x00, 0x00,
547
548
            // Dummy next arange.
549
            0x30, 0x00, 0x00, 0x00,
550
            0x00, 0x00, 0x00, 0x00,
551
            0x00, 0x00, 0x00, 0x00,
552
            0x00, 0x00, 0x00, 0x00,
553
        ];
554
555
        let rest = &mut EndianSlice::new(&buf, LittleEndian);
556
557
        let error = ArangeHeader::parse(rest, DebugArangesOffset(0x10))
558
            .expect_err("should fail to parse header");
559
        assert_eq!(error, Error::UnsupportedAddressSize(0));
560
    }
561
562
    #[test]
563
    fn test_parse_entry_ok() {
564
        let encoding = Encoding {
565
            format: Format::Dwarf32,
566
            version: 2,
567
            address_size: 4,
568
        };
569
        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09];
570
        let mut iter = ArangeEntryIter {
571
            input: EndianSlice::new(&buf, LittleEndian),
572
            encoding,
573
        };
574
        let entry = iter.next().expect("should parse entry ok");
575
        assert_eq!(
576
            iter.input,
577
            EndianSlice::new(&buf[buf.len() - 1..], LittleEndian)
578
        );
579
        assert_eq!(
580
            entry,
581
            Some(ArangeEntry {
582
                range: Range {
583
                    begin: 0x0403_0201,
584
                    end: 0x0403_0201 + 0x0807_0605,
585
                },
586
                length: 0x0807_0605,
587
            })
588
        );
589
    }
590
591
    #[test]
592
    fn test_parse_entry_zero() {
593
        let encoding = Encoding {
594
            format: Format::Dwarf32,
595
            version: 2,
596
            address_size: 4,
597
        };
598
        #[rustfmt::skip]
599
        let buf = [
600
            // Zero tuple.
601
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
602
            // Address.
603
            0x01, 0x02, 0x03, 0x04,
604
            // Length.
605
            0x05, 0x06, 0x07, 0x08,
606
            // Next tuple.
607
            0x09
608
        ];
609
        let mut iter = ArangeEntryIter {
610
            input: EndianSlice::new(&buf, LittleEndian),
611
            encoding,
612
        };
613
        let entry = iter.next().expect("should parse entry ok");
614
        assert_eq!(
615
            iter.input,
616
            EndianSlice::new(&buf[buf.len() - 1..], LittleEndian)
617
        );
618
        assert_eq!(
619
            entry,
620
            Some(ArangeEntry {
621
                range: Range {
622
                    begin: 0x0403_0201,
623
                    end: 0x0403_0201 + 0x0807_0605,
624
                },
625
                length: 0x0807_0605,
626
            })
627
        );
628
    }
629
630
    #[test]
631
    fn test_parse_entry_overflow_32() {
632
        let encoding = Encoding {
633
            format: Format::Dwarf32,
634
            version: 2,
635
            address_size: 4,
636
        };
637
        #[rustfmt::skip]
638
        let buf = [
639
            // Address.
640
            0x01, 0x02, 0x03, 0x84,
641
            // Length.
642
            0x05, 0x06, 0x07, 0x88,
643
            // Next tuple.
644
            0x09
645
        ];
646
        let mut iter = ArangeEntryIter {
647
            input: EndianSlice::new(&buf, LittleEndian),
648
            encoding,
649
        };
650
        let entry = iter.next();
651
        assert_eq!(
652
            iter.input,
653
            EndianSlice::new(&buf[buf.len() - 1..], LittleEndian)
654
        );
655
        assert_eq!(entry, Err(Error::AddressOverflow));
656
    }
657
658
    #[test]
659
    fn test_parse_entry_overflow_64() {
660
        let encoding = Encoding {
661
            format: Format::Dwarf32,
662
            version: 2,
663
            address_size: 8,
664
        };
665
        #[rustfmt::skip]
666
        let buf = [
667
            // Address.
668
            0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x80,
669
            // Length.
670
            0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x80,
671
            // Next tuple.
672
            0x09
673
        ];
674
        let mut iter = ArangeEntryIter {
675
            input: EndianSlice::new(&buf, LittleEndian),
676
            encoding,
677
        };
678
        let entry = iter.next();
679
        assert_eq!(
680
            iter.input,
681
            EndianSlice::new(&buf[buf.len() - 1..], LittleEndian)
682
        );
683
        assert_eq!(entry, Err(Error::AddressOverflow));
684
    }
685
686
    #[test]
687
    fn test_parse_entry_tombstone_32() {
688
        let encoding = Encoding {
689
            format: Format::Dwarf32,
690
            version: 2,
691
            address_size: 4,
692
        };
693
        #[rustfmt::skip]
694
        let buf = [
695
            // Address.
696
            0xff, 0xff, 0xff, 0xff,
697
            // Length.
698
            0x05, 0x06, 0x07, 0x08,
699
            // Address.
700
            0x01, 0x02, 0x03, 0x04,
701
            // Length.
702
            0x05, 0x06, 0x07, 0x08,
703
            // Next tuple.
704
            0x09
705
        ];
706
707
        let mut iter = ArangeEntryIter {
708
            input: EndianSlice::new(&buf, LittleEndian),
709
            encoding,
710
        };
711
        let entry = iter.next_raw().unwrap();
712
        assert_eq!(
713
            iter.input,
714
            EndianSlice::new(&buf[buf.len() - 9..], LittleEndian)
715
        );
716
        assert_eq!(
717
            entry,
718
            Some(ArangeEntry {
719
                range: Range {
720
                    begin: 0xffff_ffff,
721
                    end: 0,
722
                },
723
                length: 0x0807_0605,
724
            })
725
        );
726
727
        let mut iter = ArangeEntryIter {
728
            input: EndianSlice::new(&buf, LittleEndian),
729
            encoding,
730
        };
731
        let entry = iter.next().unwrap();
732
        assert_eq!(
733
            iter.input,
734
            EndianSlice::new(&buf[buf.len() - 1..], LittleEndian)
735
        );
736
        assert_eq!(
737
            entry,
738
            Some(ArangeEntry {
739
                range: Range {
740
                    begin: 0x0403_0201,
741
                    end: 0x0403_0201 + 0x0807_0605,
742
                },
743
                length: 0x0807_0605,
744
            })
745
        );
746
    }
747
748
    #[test]
749
    fn test_parse_entry_tombstone_64() {
750
        let encoding = Encoding {
751
            format: Format::Dwarf32,
752
            version: 2,
753
            address_size: 8,
754
        };
755
        #[rustfmt::skip]
756
        let buf = [
757
            // Address.
758
            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
759
            // Length.
760
            0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00,
761
            // Address.
762
            0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00,
763
            // Length.
764
            0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00,
765
            // Next tuple.
766
            0x09
767
        ];
768
769
        let mut iter = ArangeEntryIter {
770
            input: EndianSlice::new(&buf, LittleEndian),
771
            encoding,
772
        };
773
        let entry = iter.next_raw().unwrap();
774
        assert_eq!(
775
            iter.input,
776
            EndianSlice::new(&buf[buf.len() - 17..], LittleEndian)
777
        );
778
        assert_eq!(
779
            entry,
780
            Some(ArangeEntry {
781
                range: Range {
782
                    begin: 0xffff_ffff_ffff_ffff,
783
                    end: 0,
784
                },
785
                length: 0x0807_0605,
786
            })
787
        );
788
789
        let mut iter = ArangeEntryIter {
790
            input: EndianSlice::new(&buf, LittleEndian),
791
            encoding,
792
        };
793
        let entry = iter.next().unwrap();
794
        assert_eq!(
795
            iter.input,
796
            EndianSlice::new(&buf[buf.len() - 1..], LittleEndian)
797
        );
798
        assert_eq!(
799
            entry,
800
            Some(ArangeEntry {
801
                range: Range {
802
                    begin: 0x0403_0201,
803
                    end: 0x0403_0201 + 0x0807_0605,
804
                },
805
                length: 0x0807_0605,
806
            })
807
        );
808
    }
809
}