Coverage Report

Created: 2024-10-16 07:58

/rust/registry/src/index.crates.io-6f17d22bba15001f/gimli-0.29.0/src/read/aranges.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::common::{DebugArangesOffset, DebugInfoOffset, Encoding, SectionId};
2
use crate::endianity::Endianity;
3
use crate::read::{EndianSlice, Error, Range, Reader, ReaderOffset, Result, Section};
4
5
/// The `DebugAranges` struct represents the DWARF address range information
6
/// found in the `.debug_aranges` section.
7
#[derive(Debug, Default, Clone, Copy)]
8
pub struct DebugAranges<R> {
9
    section: R,
10
}
11
12
impl<'input, Endian> DebugAranges<EndianSlice<'input, Endian>>
13
where
14
    Endian: Endianity,
15
{
16
    /// Construct a new `DebugAranges` instance from the data in the `.debug_aranges`
17
    /// section.
18
    ///
19
    /// It is the caller's responsibility to read the `.debug_aranges` section and
20
    /// present it as a `&[u8]` slice. That means using some ELF loader on
21
    /// Linux, a Mach-O loader on macOS, etc.
22
    ///
23
    /// ```
24
    /// use gimli::{DebugAranges, LittleEndian};
25
    ///
26
    /// # let buf = [];
27
    /// # let read_debug_aranges_section = || &buf;
28
    /// let debug_aranges =
29
    ///     DebugAranges::new(read_debug_aranges_section(), LittleEndian);
30
    /// ```
31
0
    pub fn new(section: &'input [u8], endian: Endian) -> Self {
32
0
        DebugAranges {
33
0
            section: EndianSlice::new(section, endian),
34
0
        }
35
0
    }
36
}
37
38
impl<R: Reader> DebugAranges<R> {
39
    /// Iterate the sets of entries in the `.debug_aranges` section.
40
    ///
41
    /// Each set of entries belongs to a single unit.
42
0
    pub fn headers(&self) -> ArangeHeaderIter<R> {
43
0
        ArangeHeaderIter {
44
0
            input: self.section.clone(),
45
0
            offset: DebugArangesOffset(R::Offset::from_u8(0)),
46
0
        }
47
0
    }
Unexecuted instantiation: <gimli::read::aranges::DebugAranges<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::headers
Unexecuted instantiation: <gimli::read::aranges::DebugAranges<_>>::headers
48
49
    /// Get the header at the given offset.
50
0
    pub fn header(&self, offset: DebugArangesOffset<R::Offset>) -> Result<ArangeHeader<R>> {
51
0
        let mut input = self.section.clone();
52
0
        input.skip(offset.0)?;
53
0
        ArangeHeader::parse(&mut input, offset)
54
0
    }
Unexecuted instantiation: <gimli::read::aranges::DebugAranges<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::header
Unexecuted instantiation: <gimli::read::aranges::DebugAranges<_>>::header
55
}
56
57
impl<T> DebugAranges<T> {
58
    /// Create a `DebugAranges` section that references the data in `self`.
59
    ///
60
    /// This is useful when `R` implements `Reader` but `T` does not.
61
    ///
62
    /// Used by `DwarfSections::borrow`.
63
0
    pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAranges<R>
64
0
    where
65
0
        F: FnMut(&'a T) -> R,
66
0
    {
67
0
        borrow(&self.section).into()
68
0
    }
69
}
70
71
impl<R> Section<R> for DebugAranges<R> {
72
0
    fn id() -> SectionId {
73
0
        SectionId::DebugAranges
74
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
75
76
0
    fn reader(&self) -> &R {
77
0
        &self.section
78
0
    }
79
}
80
81
impl<R> From<R> for DebugAranges<R> {
82
0
    fn from(section: R) -> Self {
83
0
        DebugAranges { section }
84
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
85
}
86
87
/// An iterator over the headers of a `.debug_aranges` section.
88
#[derive(Clone, Debug)]
89
pub struct ArangeHeaderIter<R: Reader> {
90
    input: R,
91
    offset: DebugArangesOffset<R::Offset>,
92
}
93
94
impl<R: Reader> ArangeHeaderIter<R> {
95
    /// Advance the iterator to the next header.
96
0
    pub fn next(&mut self) -> Result<Option<ArangeHeader<R>>> {
97
0
        if self.input.is_empty() {
98
0
            return Ok(None);
99
0
        }
100
0
101
0
        let len = self.input.len();
102
0
        match ArangeHeader::parse(&mut self.input, self.offset) {
103
0
            Ok(header) => {
104
0
                self.offset.0 += len - self.input.len();
105
0
                Ok(Some(header))
106
            }
107
0
            Err(e) => {
108
0
                self.input.empty();
109
0
                Err(e)
110
            }
111
        }
112
0
    }
Unexecuted instantiation: <gimli::read::aranges::ArangeHeaderIter<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::next
Unexecuted instantiation: <gimli::read::aranges::ArangeHeaderIter<_>>::next
113
}
114
115
#[cfg(feature = "fallible-iterator")]
116
impl<R: Reader> fallible_iterator::FallibleIterator for ArangeHeaderIter<R> {
117
    type Item = ArangeHeader<R>;
118
    type Error = Error;
119
120
    fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
121
        ArangeHeaderIter::next(self)
122
    }
123
}
124
125
/// A header for a set of entries in the `.debug_arange` section.
126
///
127
/// These entries all belong to a single unit.
128
#[derive(Debug, Clone, PartialEq, Eq)]
129
pub struct ArangeHeader<R, Offset = <R as Reader>::Offset>
130
where
131
    R: Reader<Offset = Offset>,
132
    Offset: ReaderOffset,
133
{
134
    offset: DebugArangesOffset<Offset>,
135
    encoding: Encoding,
136
    length: Offset,
137
    debug_info_offset: DebugInfoOffset<Offset>,
138
    segment_size: u8,
139
    entries: R,
140
}
141
142
impl<R, Offset> ArangeHeader<R, Offset>
143
where
144
    R: Reader<Offset = Offset>,
145
    Offset: ReaderOffset,
146
{
147
0
    fn parse(input: &mut R, offset: DebugArangesOffset<Offset>) -> Result<Self> {
148
0
        let (length, format) = input.read_initial_length()?;
149
0
        let mut rest = input.split(length)?;
150
151
        // Check the version. The DWARF 5 spec says that this is always 2, but version 3
152
        // has been observed in the wild, potentially due to a bug; see
153
        // https://github.com/gimli-rs/gimli/issues/559 for more information.
154
        // lldb allows versions 2 through 5, possibly by mistake.
155
0
        let version = rest.read_u16()?;
156
0
        if version != 2 && version != 3 {
157
0
            return Err(Error::UnknownVersion(u64::from(version)));
158
0
        }
159
160
0
        let debug_info_offset = rest.read_offset(format).map(DebugInfoOffset)?;
161
0
        let address_size = rest.read_u8()?;
162
0
        let segment_size = rest.read_u8()?;
163
164
        // unit_length + version + offset + address_size + segment_size
165
0
        let header_length = format.initial_length_size() + 2 + format.word_size() + 1 + 1;
166
167
        // The first tuple following the header in each set begins at an offset that is
168
        // a multiple of the size of a single tuple (that is, the size of a segment selector
169
        // plus twice the size of an address).
170
0
        let tuple_length = address_size
171
0
            .checked_mul(2)
172
0
            .and_then(|x| x.checked_add(segment_size))
Unexecuted instantiation: <gimli::read::aranges::ArangeHeader<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>, usize>>::parse::{closure#0}
Unexecuted instantiation: <gimli::read::aranges::ArangeHeader<_, _>>::parse::{closure#0}
173
0
            .ok_or(Error::InvalidAddressRange)?;
174
0
        if tuple_length == 0 {
175
0
            return Err(Error::InvalidAddressRange);
176
0
        }
177
0
        let padding = if header_length % tuple_length == 0 {
178
0
            0
179
        } else {
180
0
            tuple_length - header_length % tuple_length
181
        };
182
0
        rest.skip(R::Offset::from_u8(padding))?;
183
184
0
        let encoding = Encoding {
185
0
            format,
186
0
            version,
187
0
            address_size,
188
0
            // TODO: segment_size
189
0
        };
190
0
        Ok(ArangeHeader {
191
0
            offset,
192
0
            encoding,
193
0
            length,
194
0
            debug_info_offset,
195
0
            segment_size,
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 segment size for this set of entries.
219
    #[inline]
220
0
    pub fn segment_size(&self) -> u8 {
221
0
        self.segment_size
222
0
    }
223
224
    /// Return the offset into the .debug_info section for this set of arange entries.
225
    #[inline]
226
0
    pub fn debug_info_offset(&self) -> DebugInfoOffset<Offset> {
227
0
        self.debug_info_offset
228
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
229
230
    /// Return the arange entries in this set.
231
    #[inline]
232
0
    pub fn entries(&self) -> ArangeEntryIter<R> {
233
0
        ArangeEntryIter {
234
0
            input: self.entries.clone(),
235
0
            encoding: self.encoding,
236
0
            segment_size: self.segment_size,
237
0
        }
238
0
    }
Unexecuted instantiation: <gimli::read::aranges::ArangeHeader<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>, usize>>::entries
Unexecuted instantiation: <gimli::read::aranges::ArangeHeader<_, _>>::entries
239
}
240
241
/// An iterator over the aranges from a `.debug_aranges` section.
242
///
243
/// Can be [used with
244
/// `FallibleIterator`](./index.html#using-with-fallibleiterator).
245
#[derive(Debug, Clone)]
246
pub struct ArangeEntryIter<R: Reader> {
247
    input: R,
248
    encoding: Encoding,
249
    segment_size: u8,
250
}
251
252
impl<R: Reader> ArangeEntryIter<R> {
253
    /// Advance the iterator and return the next arange.
254
    ///
255
    /// Returns the newly parsed arange as `Ok(Some(arange))`. Returns `Ok(None)`
256
    /// when iteration is complete and all aranges have already been parsed and
257
    /// yielded. If an error occurs while parsing the next arange, then this error
258
    /// is returned as `Err(e)`, and all subsequent calls return `Ok(None)`.
259
0
    pub fn next(&mut self) -> Result<Option<ArangeEntry>> {
260
0
        if self.input.is_empty() {
261
0
            return Ok(None);
262
0
        }
263
0
264
0
        match ArangeEntry::parse(&mut self.input, self.encoding, self.segment_size) {
265
0
            Ok(Some(entry)) => Ok(Some(entry)),
266
            Ok(None) => {
267
0
                self.input.empty();
268
0
                Ok(None)
269
            }
270
0
            Err(e) => {
271
0
                self.input.empty();
272
0
                Err(e)
273
            }
274
        }
275
0
    }
Unexecuted instantiation: <gimli::read::aranges::ArangeEntryIter<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::next
Unexecuted instantiation: <gimli::read::aranges::ArangeEntryIter<_>>::next
276
}
277
278
#[cfg(feature = "fallible-iterator")]
279
impl<R: Reader> fallible_iterator::FallibleIterator for ArangeEntryIter<R> {
280
    type Item = ArangeEntry;
281
    type Error = Error;
282
283
    fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
284
        ArangeEntryIter::next(self)
285
    }
286
}
287
288
/// A single parsed arange.
289
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
290
pub struct ArangeEntry {
291
    segment: Option<u64>,
292
    address: u64,
293
    length: u64,
294
}
295
296
impl ArangeEntry {
297
    /// Parse a single arange. Return `None` for the null arange, `Some` for an actual arange.
298
0
    fn parse<R: Reader>(
299
0
        input: &mut R,
300
0
        encoding: Encoding,
301
0
        segment_size: u8,
302
0
    ) -> Result<Option<Self>> {
303
0
        let address_size = encoding.address_size;
304
0
305
0
        let tuple_length = R::Offset::from_u8(2 * address_size + segment_size);
306
0
        if tuple_length > input.len() {
307
0
            input.empty();
308
0
            return Ok(None);
309
0
        }
310
311
0
        let segment = if segment_size != 0 {
312
0
            input.read_address(segment_size)?
313
        } else {
314
0
            0
315
        };
316
0
        let address = input.read_address(address_size)?;
317
0
        let length = input.read_address(address_size)?;
318
319
0
        match (segment, address, length) {
320
            // This is meant to be a null terminator, but in practice it can occur
321
            // before the end, possibly due to a linker omitting a function and
322
            // leaving an unrelocated entry.
323
0
            (0, 0, 0) => Self::parse(input, encoding, segment_size),
324
            _ => Ok(Some(ArangeEntry {
325
0
                segment: if segment_size != 0 {
326
0
                    Some(segment)
327
                } else {
328
0
                    None
329
                },
330
0
                address,
331
0
                length,
332
            })),
333
        }
334
0
    }
Unexecuted instantiation: <gimli::read::aranges::ArangeEntry>::parse::<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>
Unexecuted instantiation: <gimli::read::aranges::ArangeEntry>::parse::<_>
335
336
    /// Return the segment selector of this arange.
337
    #[inline]
338
0
    pub fn segment(&self) -> Option<u64> {
339
0
        self.segment
340
0
    }
341
342
    /// Return the beginning address of this arange.
343
    #[inline]
344
0
    pub fn address(&self) -> u64 {
345
0
        self.address
346
0
    }
347
348
    /// Return the length of this arange.
349
    #[inline]
350
0
    pub fn length(&self) -> u64 {
351
0
        self.length
352
0
    }
Unexecuted instantiation: <gimli::read::aranges::ArangeEntry>::length
Unexecuted instantiation: <gimli::read::aranges::ArangeEntry>::length
353
354
    /// Return the range.
355
    #[inline]
356
0
    pub fn range(&self) -> Range {
357
0
        Range {
358
0
            begin: self.address,
359
0
            end: self.address.wrapping_add(self.length),
360
0
        }
361
0
    }
Unexecuted instantiation: <gimli::read::aranges::ArangeEntry>::range
Unexecuted instantiation: <gimli::read::aranges::ArangeEntry>::range
362
}
363
364
#[cfg(test)]
365
mod tests {
366
    use super::*;
367
    use crate::common::{DebugInfoOffset, Format};
368
    use crate::endianity::LittleEndian;
369
    use crate::read::EndianSlice;
370
371
    #[test]
372
    fn test_iterate_headers() {
373
        #[rustfmt::skip]
374
        let buf = [
375
            // 32-bit length = 28.
376
            0x1c, 0x00, 0x00, 0x00,
377
            // Version.
378
            0x02, 0x00,
379
            // Offset.
380
            0x01, 0x02, 0x03, 0x04,
381
            // Address size.
382
            0x04,
383
            // Segment size.
384
            0x00,
385
            // Dummy padding and arange tuples.
386
            0x00, 0x00, 0x00, 0x00,
387
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
388
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
389
390
            // 32-bit length = 36.
391
            0x24, 0x00, 0x00, 0x00,
392
            // Version.
393
            0x02, 0x00,
394
            // Offset.
395
            0x11, 0x12, 0x13, 0x14,
396
            // Address size.
397
            0x04,
398
            // Segment size.
399
            0x00,
400
            // Dummy padding and arange tuples.
401
            0x00, 0x00, 0x00, 0x00,
402
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
403
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
404
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
405
        ];
406
407
        let debug_aranges = DebugAranges::new(&buf, LittleEndian);
408
        let mut headers = debug_aranges.headers();
409
410
        let header = headers
411
            .next()
412
            .expect("should parse header ok")
413
            .expect("should have a header");
414
        assert_eq!(header.offset(), DebugArangesOffset(0));
415
        assert_eq!(header.debug_info_offset(), DebugInfoOffset(0x0403_0201));
416
417
        let header = headers
418
            .next()
419
            .expect("should parse header ok")
420
            .expect("should have a header");
421
        assert_eq!(header.offset(), DebugArangesOffset(0x20));
422
        assert_eq!(header.debug_info_offset(), DebugInfoOffset(0x1413_1211));
423
    }
424
425
    #[test]
426
    fn test_parse_header_ok() {
427
        #[rustfmt::skip]
428
        let buf = [
429
            // 32-bit length = 32.
430
            0x20, 0x00, 0x00, 0x00,
431
            // Version.
432
            0x02, 0x00,
433
            // Offset.
434
            0x01, 0x02, 0x03, 0x04,
435
            // Address size.
436
            0x08,
437
            // Segment size.
438
            0x04,
439
            // Length to here = 12, tuple length = 20.
440
            // Padding to tuple length multiple = 4.
441
            0x10, 0x00, 0x00, 0x00,
442
            0x00, 0x00, 0x00, 0x00,
443
444
            // Dummy arange tuple data.
445
            0x20, 0x00, 0x00, 0x00,
446
            0x00, 0x00, 0x00, 0x00,
447
            0x00, 0x00, 0x00, 0x00,
448
            0x00, 0x00, 0x00, 0x00,
449
450
            // Dummy next arange.
451
            0x30, 0x00, 0x00, 0x00,
452
            0x00, 0x00, 0x00, 0x00,
453
            0x00, 0x00, 0x00, 0x00,
454
            0x00, 0x00, 0x00, 0x00,
455
        ];
456
457
        let rest = &mut EndianSlice::new(&buf, LittleEndian);
458
459
        let header =
460
            ArangeHeader::parse(rest, DebugArangesOffset(0x10)).expect("should parse header ok");
461
462
        assert_eq!(
463
            *rest,
464
            EndianSlice::new(&buf[buf.len() - 16..], LittleEndian)
465
        );
466
        assert_eq!(
467
            header,
468
            ArangeHeader {
469
                offset: DebugArangesOffset(0x10),
470
                encoding: Encoding {
471
                    format: Format::Dwarf32,
472
                    version: 2,
473
                    address_size: 8,
474
                },
475
                length: 0x20,
476
                debug_info_offset: DebugInfoOffset(0x0403_0201),
477
                segment_size: 4,
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
            0xff,
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::InvalidAddressRange);
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::InvalidAddressRange);
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 segment_size = 0;
570
        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09];
571
        let rest = &mut EndianSlice::new(&buf, LittleEndian);
572
        let entry =
573
            ArangeEntry::parse(rest, encoding, segment_size).expect("should parse entry ok");
574
        assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
575
        assert_eq!(
576
            entry,
577
            Some(ArangeEntry {
578
                segment: None,
579
                address: 0x0403_0201,
580
                length: 0x0807_0605,
581
            })
582
        );
583
    }
584
585
    #[test]
586
    fn test_parse_entry_segment() {
587
        let encoding = Encoding {
588
            format: Format::Dwarf32,
589
            version: 2,
590
            address_size: 4,
591
        };
592
        let segment_size = 8;
593
        #[rustfmt::skip]
594
        let buf = [
595
            // Segment.
596
            0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
597
            // Address.
598
            0x01, 0x02, 0x03, 0x04,
599
            // Length.
600
            0x05, 0x06, 0x07, 0x08,
601
            // Next tuple.
602
            0x09
603
        ];
604
        let rest = &mut EndianSlice::new(&buf, LittleEndian);
605
        let entry =
606
            ArangeEntry::parse(rest, encoding, segment_size).expect("should parse entry ok");
607
        assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
608
        assert_eq!(
609
            entry,
610
            Some(ArangeEntry {
611
                segment: Some(0x1817_1615_1413_1211),
612
                address: 0x0403_0201,
613
                length: 0x0807_0605,
614
            })
615
        );
616
    }
617
618
    #[test]
619
    fn test_parse_entry_zero() {
620
        let encoding = Encoding {
621
            format: Format::Dwarf32,
622
            version: 2,
623
            address_size: 4,
624
        };
625
        let segment_size = 0;
626
        #[rustfmt::skip]
627
        let buf = [
628
            // Zero tuple.
629
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630
            // Address.
631
            0x01, 0x02, 0x03, 0x04,
632
            // Length.
633
            0x05, 0x06, 0x07, 0x08,
634
            // Next tuple.
635
            0x09
636
        ];
637
        let rest = &mut EndianSlice::new(&buf, LittleEndian);
638
        let entry =
639
            ArangeEntry::parse(rest, encoding, segment_size).expect("should parse entry ok");
640
        assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
641
        assert_eq!(
642
            entry,
643
            Some(ArangeEntry {
644
                segment: None,
645
                address: 0x0403_0201,
646
                length: 0x0807_0605,
647
            })
648
        );
649
    }
650
}