Coverage Report

Created: 2026-03-26 07:41

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/cfi.rs
Line
Count
Source
1
#[cfg(feature = "read")]
2
use alloc::boxed::Box;
3
4
use core::cmp::Ordering;
5
use core::fmt::{self, Debug};
6
use core::iter::FromIterator;
7
use core::mem;
8
use core::num::Wrapping;
9
10
use super::util::{ArrayLike, ArrayVec};
11
use crate::common::{
12
    DebugFrameOffset, EhFrameOffset, Encoding, Format, Register, SectionId, Vendor,
13
};
14
use crate::constants::{self, DwEhPe};
15
use crate::endianity::Endianity;
16
use crate::read::{
17
    EndianSlice, Error, Expression, Reader, ReaderAddress, ReaderOffset, Result, Section,
18
    StoreOnHeap,
19
};
20
21
/// `DebugFrame` contains the `.debug_frame` section's frame unwinding
22
/// information required to unwind to and recover registers from older frames on
23
/// the stack. For example, this is useful for a debugger that wants to print
24
/// locals in a backtrace.
25
///
26
/// Most interesting methods are defined in the
27
/// [`UnwindSection`](trait.UnwindSection.html) trait.
28
///
29
/// ### Differences between `.debug_frame` and `.eh_frame`
30
///
31
/// While the `.debug_frame` section's information has a lot of overlap with the
32
/// `.eh_frame` section's information, the `.eh_frame` information tends to only
33
/// encode the subset of information needed for exception handling. Often, only
34
/// one of `.eh_frame` or `.debug_frame` will be present in an object file.
35
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
36
pub struct DebugFrame<R: Reader> {
37
    section: R,
38
    address_size: u8,
39
    vendor: Vendor,
40
}
41
42
impl<R: Reader> DebugFrame<R> {
43
    /// Set the size of a target address in bytes.
44
    ///
45
    /// This defaults to the native word size.
46
    /// This is only used if the CIE version is less than 4.
47
0
    pub fn set_address_size(&mut self, address_size: u8) {
48
0
        self.address_size = address_size
49
0
    }
50
51
    /// Set the vendor extensions to use.
52
    ///
53
    /// This defaults to `Vendor::Default`.
54
0
    pub fn set_vendor(&mut self, vendor: Vendor) {
55
0
        self.vendor = vendor;
56
0
    }
57
}
58
59
impl<'input, Endian> DebugFrame<EndianSlice<'input, Endian>>
60
where
61
    Endian: Endianity,
62
{
63
    /// Construct a new `DebugFrame` instance from the data in the
64
    /// `.debug_frame` section.
65
    ///
66
    /// It is the caller's responsibility to read the section and present it as
67
    /// a `&[u8]` slice. That means using some ELF loader on Linux, a Mach-O
68
    /// loader on macOS, etc.
69
    ///
70
    /// ```
71
    /// use gimli::{DebugFrame, NativeEndian};
72
    ///
73
    /// // Use with `.debug_frame`
74
    /// # let buf = [0x00, 0x01, 0x02, 0x03];
75
    /// # let read_debug_frame_section_somehow = || &buf;
76
    /// let debug_frame = DebugFrame::new(read_debug_frame_section_somehow(), NativeEndian);
77
    /// ```
78
0
    pub fn new(section: &'input [u8], endian: Endian) -> Self {
79
0
        Self::from(EndianSlice::new(section, endian))
80
0
    }
81
}
82
83
impl<R: Reader> Section<R> for DebugFrame<R> {
84
0
    fn id() -> SectionId {
85
0
        SectionId::DebugFrame
86
0
    }
87
88
0
    fn reader(&self) -> &R {
89
0
        &self.section
90
0
    }
91
}
92
93
impl<R: Reader> From<R> for DebugFrame<R> {
94
0
    fn from(section: R) -> Self {
95
        // Default to native word size.
96
0
        DebugFrame {
97
0
            section,
98
0
            address_size: mem::size_of::<usize>() as u8,
99
0
            vendor: Vendor::Default,
100
0
        }
101
0
    }
102
}
103
104
/// `EhFrameHdr` contains the information about the `.eh_frame_hdr` section.
105
///
106
/// A pointer to the start of the `.eh_frame` data, and optionally, a binary
107
/// search table of pointers to the `.eh_frame` records that are found in this section.
108
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
109
pub struct EhFrameHdr<R: Reader>(R);
110
111
/// `ParsedEhFrameHdr` contains the parsed information from the `.eh_frame_hdr` section.
112
#[derive(Clone, Debug)]
113
pub struct ParsedEhFrameHdr<R: Reader> {
114
    address_size: u8,
115
    section: R,
116
117
    eh_frame_ptr: Pointer,
118
    fde_count: u64,
119
    table_enc: DwEhPe,
120
    table: R,
121
}
122
123
impl<'input, Endian> EhFrameHdr<EndianSlice<'input, Endian>>
124
where
125
    Endian: Endianity,
126
{
127
    /// Constructs a new `EhFrameHdr` instance from the data in the `.eh_frame_hdr` section.
128
0
    pub fn new(section: &'input [u8], endian: Endian) -> Self {
129
0
        Self::from(EndianSlice::new(section, endian))
130
0
    }
131
}
132
133
impl<R: Reader> EhFrameHdr<R> {
134
    /// Parses this `EhFrameHdr` to a `ParsedEhFrameHdr`.
135
0
    pub fn parse(&self, bases: &BaseAddresses, address_size: u8) -> Result<ParsedEhFrameHdr<R>> {
136
0
        let mut reader = self.0.clone();
137
0
        let version = reader.read_u8()?;
138
0
        if version != 1 {
139
0
            return Err(Error::UnknownVersion(u64::from(version)));
140
0
        }
141
142
0
        let eh_frame_ptr_enc = parse_pointer_encoding(&mut reader)?;
143
0
        let fde_count_enc = parse_pointer_encoding(&mut reader)?;
144
0
        let table_enc = parse_pointer_encoding(&mut reader)?;
145
146
0
        let parameters = PointerEncodingParameters {
147
0
            bases: &bases.eh_frame_hdr,
148
0
            func_base: None,
149
0
            address_size,
150
0
            section: &self.0,
151
0
        };
152
153
        // Omitting this pointer is not valid (defeats the purpose of .eh_frame_hdr entirely)
154
0
        if eh_frame_ptr_enc == constants::DW_EH_PE_omit {
155
0
            return Err(Error::CannotParseOmitPointerEncoding);
156
0
        }
157
0
        let eh_frame_ptr = parse_encoded_pointer(eh_frame_ptr_enc, &parameters, &mut reader)?;
158
159
        let fde_count;
160
0
        if fde_count_enc == constants::DW_EH_PE_omit || table_enc == constants::DW_EH_PE_omit {
161
0
            fde_count = 0
162
        } else {
163
0
            if fde_count_enc != fde_count_enc.format() {
164
0
                return Err(Error::UnsupportedPointerEncoding);
165
0
            }
166
0
            fde_count = parse_encoded_value(fde_count_enc, &parameters, &mut reader)?;
167
        }
168
169
0
        Ok(ParsedEhFrameHdr {
170
0
            address_size,
171
0
            section: self.0.clone(),
172
0
173
0
            eh_frame_ptr,
174
0
            fde_count,
175
0
            table_enc,
176
0
            table: reader,
177
0
        })
178
0
    }
179
}
180
181
impl<R: Reader> Section<R> for EhFrameHdr<R> {
182
0
    fn id() -> SectionId {
183
0
        SectionId::EhFrameHdr
184
0
    }
185
186
0
    fn reader(&self) -> &R {
187
0
        &self.0
188
0
    }
189
}
190
191
impl<R: Reader> From<R> for EhFrameHdr<R> {
192
0
    fn from(section: R) -> Self {
193
0
        EhFrameHdr(section)
194
0
    }
195
}
196
197
impl<R: Reader> ParsedEhFrameHdr<R> {
198
    /// Returns the address of the binary's `.eh_frame` section.
199
0
    pub fn eh_frame_ptr(&self) -> Pointer {
200
0
        self.eh_frame_ptr
201
0
    }
202
203
    /// Retrieves the CFI binary search table, if there is one.
204
0
    pub fn table(&self) -> Option<EhHdrTable<'_, R>> {
205
        // There are two big edge cases here:
206
        // * You search the table for an invalid address. As this is just a binary
207
        //   search table, we always have to return a valid result for that (unless
208
        //   you specify an address that is lower than the first address in the
209
        //   table). Since this means that you have to recheck that the FDE contains
210
        //   your address anyways, we just return the first FDE even when the address
211
        //   is too low. After all, we're just doing a normal binary search.
212
        // * This falls apart when the table is empty - there is no entry we could
213
        //   return. We conclude that an empty table is not really a table at all.
214
0
        if self.fde_count == 0 {
215
0
            None
216
        } else {
217
0
            Some(EhHdrTable { hdr: self })
218
        }
219
0
    }
220
}
221
222
/// An iterator for `.eh_frame_hdr` section's binary search table.
223
///
224
/// Each table entry consists of a tuple containing an  `initial_location` and `address`.
225
/// The `initial location` represents the first address that the targeted FDE
226
/// is able to decode. The `address` is the address of the FDE in the `.eh_frame` section.
227
/// The `address` can be converted with `EhHdrTable::pointer_to_offset` and `EhFrame::fde_from_offset` to an FDE.
228
#[derive(Debug)]
229
pub struct EhHdrTableIter<'a, 'bases, R: Reader> {
230
    hdr: &'a ParsedEhFrameHdr<R>,
231
    table: R,
232
    bases: &'bases BaseAddresses,
233
    remain: u64,
234
}
235
236
impl<'a, 'bases, R: Reader> EhHdrTableIter<'a, 'bases, R> {
237
    /// Yield the next entry in the `EhHdrTableIter`.
238
0
    pub fn next(&mut self) -> Result<Option<(Pointer, Pointer)>> {
239
0
        if self.remain == 0 {
240
0
            return Ok(None);
241
0
        }
242
243
0
        let parameters = PointerEncodingParameters {
244
0
            bases: &self.bases.eh_frame_hdr,
245
0
            func_base: None,
246
0
            address_size: self.hdr.address_size,
247
0
            section: &self.hdr.section,
248
0
        };
249
250
0
        self.remain -= 1;
251
0
        let from = parse_encoded_pointer(self.hdr.table_enc, &parameters, &mut self.table)?;
252
0
        let to = parse_encoded_pointer(self.hdr.table_enc, &parameters, &mut self.table)?;
253
0
        Ok(Some((from, to)))
254
0
    }
255
    /// Yield the nth entry in the `EhHdrTableIter`
256
0
    pub fn nth(&mut self, n: usize) -> Result<Option<(Pointer, Pointer)>> {
257
        use core::convert::TryFrom;
258
0
        let size = match self.hdr.table_enc.format() {
259
            constants::DW_EH_PE_uleb128 | constants::DW_EH_PE_sleb128 => {
260
0
                return Err(Error::VariableLengthSearchTable);
261
            }
262
0
            constants::DW_EH_PE_sdata2 | constants::DW_EH_PE_udata2 => 2,
263
0
            constants::DW_EH_PE_sdata4 | constants::DW_EH_PE_udata4 => 4,
264
0
            constants::DW_EH_PE_sdata8 | constants::DW_EH_PE_udata8 => 8,
265
0
            _ => return Err(Error::UnknownPointerEncoding(self.hdr.table_enc)),
266
        };
267
268
0
        let row_size = size * 2;
269
0
        let n = u64::try_from(n).map_err(|_| Error::UnsupportedOffset)?;
270
0
        self.remain = self.remain.saturating_sub(n);
271
0
        self.table.skip(R::Offset::from_u64(n * row_size)?)?;
272
0
        self.next()
273
0
    }
274
}
275
276
#[cfg(feature = "fallible-iterator")]
277
impl<'a, 'bases, R: Reader> fallible_iterator::FallibleIterator for EhHdrTableIter<'a, 'bases, R> {
278
    type Item = (Pointer, Pointer);
279
    type Error = Error;
280
    fn next(&mut self) -> Result<Option<Self::Item>> {
281
        EhHdrTableIter::next(self)
282
    }
283
284
    fn size_hint(&self) -> (usize, Option<usize>) {
285
        use core::convert::TryInto;
286
        (
287
            self.remain.try_into().unwrap_or(0),
288
            self.remain.try_into().ok(),
289
        )
290
    }
291
292
    fn nth(&mut self, n: usize) -> Result<Option<Self::Item>> {
293
        EhHdrTableIter::nth(self, n)
294
    }
295
}
296
297
/// The CFI binary search table that is an optional part of the `.eh_frame_hdr` section.
298
#[derive(Debug, Clone)]
299
pub struct EhHdrTable<'a, R: Reader> {
300
    hdr: &'a ParsedEhFrameHdr<R>,
301
}
302
303
impl<'a, R: Reader + 'a> EhHdrTable<'a, R> {
304
    /// Return an iterator that can walk the `.eh_frame_hdr` table.
305
    ///
306
    /// Each table entry consists of a tuple containing an `initial_location` and `address`.
307
    /// The `initial location` represents the first address that the targeted FDE
308
    /// is able to decode. The `address` is the address of the FDE in the `.eh_frame` section.
309
    /// The `address` can be converted with `EhHdrTable::pointer_to_offset` and `EhFrame::fde_from_offset` to an FDE.
310
0
    pub fn iter<'bases>(&self, bases: &'bases BaseAddresses) -> EhHdrTableIter<'_, 'bases, R> {
311
0
        EhHdrTableIter {
312
0
            hdr: self.hdr,
313
0
            bases,
314
0
            remain: self.hdr.fde_count,
315
0
            table: self.hdr.table.clone(),
316
0
        }
317
0
    }
318
    /// *Probably* returns a pointer to the FDE for the given address.
319
    ///
320
    /// This performs a binary search, so if there is no FDE for the given address,
321
    /// this function **will** return a pointer to any other FDE that's close by.
322
    ///
323
    /// To be sure, you **must** call `contains` on the FDE.
324
0
    pub fn lookup(&self, address: u64, bases: &BaseAddresses) -> Result<Pointer> {
325
0
        let size = match self.hdr.table_enc.format() {
326
            constants::DW_EH_PE_uleb128 | constants::DW_EH_PE_sleb128 => {
327
0
                return Err(Error::VariableLengthSearchTable);
328
            }
329
0
            constants::DW_EH_PE_sdata2 | constants::DW_EH_PE_udata2 => 2,
330
0
            constants::DW_EH_PE_sdata4 | constants::DW_EH_PE_udata4 => 4,
331
0
            constants::DW_EH_PE_sdata8 | constants::DW_EH_PE_udata8 => 8,
332
0
            _ => return Err(Error::UnknownPointerEncoding(self.hdr.table_enc)),
333
        };
334
335
0
        let row_size = size * 2;
336
337
0
        let mut len = self.hdr.fde_count;
338
339
0
        let mut reader = self.hdr.table.clone();
340
341
0
        let parameters = PointerEncodingParameters {
342
0
            bases: &bases.eh_frame_hdr,
343
0
            func_base: None,
344
0
            address_size: self.hdr.address_size,
345
0
            section: &self.hdr.section,
346
0
        };
347
348
0
        while len > 1 {
349
0
            let head = reader.split(R::Offset::from_u64((len / 2) * row_size)?)?;
350
0
            let tail = reader.clone();
351
352
0
            let pivot =
353
0
                parse_encoded_pointer(self.hdr.table_enc, &parameters, &mut reader)?.direct()?;
354
355
0
            match pivot.cmp(&address) {
356
                Ordering::Equal => {
357
0
                    reader = tail;
358
0
                    break;
359
                }
360
0
                Ordering::Less => {
361
0
                    reader = tail;
362
0
                    len = len - (len / 2);
363
0
                }
364
0
                Ordering::Greater => {
365
0
                    reader = head;
366
0
                    len /= 2;
367
0
                }
368
            }
369
        }
370
371
0
        reader.skip(R::Offset::from_u64(size)?)?;
372
373
0
        parse_encoded_pointer(self.hdr.table_enc, &parameters, &mut reader)
374
0
    }
375
376
    /// Convert a `Pointer` to a section offset.
377
    ///
378
    /// This does not support indirect pointers.
379
0
    pub fn pointer_to_offset(&self, ptr: Pointer) -> Result<EhFrameOffset<R::Offset>> {
380
0
        let ptr = ptr.direct()?;
381
0
        let eh_frame_ptr = self.hdr.eh_frame_ptr().direct()?;
382
383
        // Calculate the offset in the EhFrame section
384
0
        R::Offset::from_u64(ptr - eh_frame_ptr).map(EhFrameOffset)
385
0
    }
386
387
    /// Returns a parsed FDE for the given address, or `NoUnwindInfoForAddress`
388
    /// if there are none.
389
    ///
390
    /// You must provide a function to get its associated CIE. See
391
    /// `PartialFrameDescriptionEntry::parse` for more information.
392
    ///
393
    /// # Example
394
    ///
395
    /// ```
396
    /// # use gimli::{BaseAddresses, EhFrame, ParsedEhFrameHdr, EndianSlice, NativeEndian, Error, UnwindSection};
397
    /// # fn foo() -> Result<(), Error> {
398
    /// # let eh_frame: EhFrame<EndianSlice<NativeEndian>> = unreachable!();
399
    /// # let eh_frame_hdr: ParsedEhFrameHdr<EndianSlice<NativeEndian>> = unimplemented!();
400
    /// # let addr = 0;
401
    /// # let bases = unimplemented!();
402
    /// let table = eh_frame_hdr.table().unwrap();
403
    /// let fde = table.fde_for_address(&eh_frame, &bases, addr, EhFrame::cie_from_offset)?;
404
    /// # Ok(())
405
    /// # }
406
    /// ```
407
0
    pub fn fde_for_address<F>(
408
0
        &self,
409
0
        frame: &EhFrame<R>,
410
0
        bases: &BaseAddresses,
411
0
        address: u64,
412
0
        get_cie: F,
413
0
    ) -> Result<FrameDescriptionEntry<R>>
414
0
    where
415
0
        F: FnMut(
416
0
            &EhFrame<R>,
417
0
            &BaseAddresses,
418
0
            EhFrameOffset<R::Offset>,
419
0
        ) -> Result<CommonInformationEntry<R>>,
420
    {
421
0
        let fdeptr = self.lookup(address, bases)?;
422
0
        let offset = self.pointer_to_offset(fdeptr)?;
423
0
        let entry = frame.fde_from_offset(bases, offset, get_cie)?;
424
0
        if entry.contains(address) {
425
0
            Ok(entry)
426
        } else {
427
0
            Err(Error::NoUnwindInfoForAddress)
428
        }
429
0
    }
430
431
    #[inline]
432
    #[doc(hidden)]
433
    #[deprecated(note = "Method renamed to fde_for_address; use that instead.")]
434
0
    pub fn lookup_and_parse<F>(
435
0
        &self,
436
0
        address: u64,
437
0
        bases: &BaseAddresses,
438
0
        frame: EhFrame<R>,
439
0
        get_cie: F,
440
0
    ) -> Result<FrameDescriptionEntry<R>>
441
0
    where
442
0
        F: FnMut(
443
0
            &EhFrame<R>,
444
0
            &BaseAddresses,
445
0
            EhFrameOffset<R::Offset>,
446
0
        ) -> Result<CommonInformationEntry<R>>,
447
    {
448
0
        self.fde_for_address(&frame, bases, address, get_cie)
449
0
    }
450
451
    /// Returns the frame unwind information for the given address,
452
    /// or `NoUnwindInfoForAddress` if there are none.
453
    ///
454
    /// You must provide a function to get the associated CIE. See
455
    /// `PartialFrameDescriptionEntry::parse` for more information.
456
0
    pub fn unwind_info_for_address<'ctx, F, S>(
457
0
        &self,
458
0
        frame: &EhFrame<R>,
459
0
        bases: &BaseAddresses,
460
0
        ctx: &'ctx mut UnwindContext<R::Offset, S>,
461
0
        address: u64,
462
0
        get_cie: F,
463
0
    ) -> Result<&'ctx UnwindTableRow<R::Offset, S>>
464
0
    where
465
0
        F: FnMut(
466
0
            &EhFrame<R>,
467
0
            &BaseAddresses,
468
0
            EhFrameOffset<R::Offset>,
469
0
        ) -> Result<CommonInformationEntry<R>>,
470
0
        S: UnwindContextStorage<R::Offset>,
471
    {
472
0
        let fde = self.fde_for_address(frame, bases, address, get_cie)?;
473
0
        fde.unwind_info_for_address(frame, bases, ctx, address)
474
0
    }
475
}
476
477
/// `EhFrame` contains the frame unwinding information needed during exception
478
/// handling found in the `.eh_frame` section.
479
///
480
/// Most interesting methods are defined in the
481
/// [`UnwindSection`](trait.UnwindSection.html) trait.
482
///
483
/// See
484
/// [`DebugFrame`](./struct.DebugFrame.html#differences-between-debug_frame-and-eh_frame)
485
/// for some discussion on the differences between `.debug_frame` and
486
/// `.eh_frame`.
487
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
488
pub struct EhFrame<R: Reader> {
489
    section: R,
490
    address_size: u8,
491
    vendor: Vendor,
492
}
493
494
impl<R: Reader> EhFrame<R> {
495
    /// Set the size of a target address in bytes.
496
    ///
497
    /// This defaults to the native word size.
498
0
    pub fn set_address_size(&mut self, address_size: u8) {
499
0
        self.address_size = address_size
500
0
    }
501
502
    /// Set the vendor extensions to use.
503
    ///
504
    /// This defaults to `Vendor::Default`.
505
0
    pub fn set_vendor(&mut self, vendor: Vendor) {
506
0
        self.vendor = vendor;
507
0
    }
508
}
509
510
impl<'input, Endian> EhFrame<EndianSlice<'input, Endian>>
511
where
512
    Endian: Endianity,
513
{
514
    /// Construct a new `EhFrame` instance from the data in the
515
    /// `.eh_frame` section.
516
    ///
517
    /// It is the caller's responsibility to read the section and present it as
518
    /// a `&[u8]` slice. That means using some ELF loader on Linux, a Mach-O
519
    /// loader on macOS, etc.
520
    ///
521
    /// ```
522
    /// use gimli::{EhFrame, EndianSlice, NativeEndian};
523
    ///
524
    /// // Use with `.eh_frame`
525
    /// # let buf = [0x00, 0x01, 0x02, 0x03];
526
    /// # let read_eh_frame_section_somehow = || &buf;
527
    /// let eh_frame = EhFrame::new(read_eh_frame_section_somehow(), NativeEndian);
528
    /// ```
529
0
    pub fn new(section: &'input [u8], endian: Endian) -> Self {
530
0
        Self::from(EndianSlice::new(section, endian))
531
0
    }
532
}
533
534
impl<R: Reader> Section<R> for EhFrame<R> {
535
0
    fn id() -> SectionId {
536
0
        SectionId::EhFrame
537
0
    }
538
539
0
    fn reader(&self) -> &R {
540
0
        &self.section
541
0
    }
542
}
543
544
impl<R: Reader> From<R> for EhFrame<R> {
545
0
    fn from(section: R) -> Self {
546
        // Default to native word size.
547
0
        EhFrame {
548
0
            section,
549
0
            address_size: mem::size_of::<usize>() as u8,
550
0
            vendor: Vendor::Default,
551
0
        }
552
0
    }
553
}
554
555
// This has to be `pub` to silence a warning (that is deny(..)'d by default) in
556
// rustc. Eventually, not having this `pub` will become a hard error.
557
#[doc(hidden)]
558
#[allow(missing_docs)]
559
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
560
pub enum CieOffsetEncoding {
561
    U32,
562
    U64,
563
}
564
565
/// An offset into an `UnwindSection`.
566
//
567
// Needed to avoid conflicting implementations of `Into<T>`.
568
pub trait UnwindOffset<T = usize>: Copy + Debug + Eq + From<T>
569
where
570
    T: ReaderOffset,
571
{
572
    /// Convert an `UnwindOffset<T>` into a `T`.
573
    fn into(self) -> T;
574
}
575
576
impl<T> UnwindOffset<T> for DebugFrameOffset<T>
577
where
578
    T: ReaderOffset,
579
{
580
    #[inline]
581
0
    fn into(self) -> T {
582
0
        self.0
583
0
    }
584
}
585
586
impl<T> UnwindOffset<T> for EhFrameOffset<T>
587
where
588
    T: ReaderOffset,
589
{
590
    #[inline]
591
0
    fn into(self) -> T {
592
0
        self.0
593
0
    }
594
}
595
596
/// This trait completely encapsulates everything that is different between
597
/// `.eh_frame` and `.debug_frame`, as well as all the bits that can change
598
/// between DWARF versions.
599
#[doc(hidden)]
600
pub trait _UnwindSectionPrivate<R: Reader> {
601
    /// Get the underlying section data.
602
    fn section(&self) -> &R;
603
604
    /// Returns true if the section allows a zero terminator.
605
    fn has_zero_terminator() -> bool;
606
607
    /// Return true if the given offset if the CIE sentinel, false otherwise.
608
    fn is_cie(format: Format, id: u64) -> bool;
609
610
    /// Return the CIE offset/ID encoding used by this unwind section with the
611
    /// given DWARF format.
612
    fn cie_offset_encoding(format: Format) -> CieOffsetEncoding;
613
614
    /// For `.eh_frame`, CIE offsets are relative to the current position. For
615
    /// `.debug_frame`, they are relative to the start of the section. We always
616
    /// internally store them relative to the section, so we handle translating
617
    /// `.eh_frame`'s relative offsets in this method. If the offset calculation
618
    /// underflows, return `None`.
619
    fn resolve_cie_offset(&self, base: R::Offset, offset: R::Offset) -> Option<R::Offset>;
620
621
    /// Does this version of this unwind section encode address and segment
622
    /// sizes in its CIEs?
623
    fn has_address_and_segment_sizes(version: u8) -> bool;
624
625
    /// The address size to use if `has_address_and_segment_sizes` returns false.
626
    fn address_size(&self) -> u8;
627
628
    /// The vendor extensions to use.
629
    fn vendor(&self) -> Vendor;
630
}
631
632
/// A section holding unwind information: either `.debug_frame` or
633
/// `.eh_frame`. See [`DebugFrame`](./struct.DebugFrame.html) and
634
/// [`EhFrame`](./struct.EhFrame.html) respectively.
635
pub trait UnwindSection<R: Reader>: Clone + Debug + _UnwindSectionPrivate<R> {
636
    /// The offset type associated with this CFI section. Either
637
    /// `DebugFrameOffset` or `EhFrameOffset`.
638
    type Offset: UnwindOffset<R::Offset>;
639
640
    /// Iterate over the `CommonInformationEntry`s and `FrameDescriptionEntry`s
641
    /// in this `.debug_frame` section.
642
    ///
643
    /// Can be [used with
644
    /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
645
0
    fn entries<'bases>(&self, bases: &'bases BaseAddresses) -> CfiEntriesIter<'bases, Self, R> {
646
0
        CfiEntriesIter {
647
0
            section: self.clone(),
648
0
            bases,
649
0
            input: self.section().clone(),
650
0
        }
651
0
    }
652
653
    /// Parse the `CommonInformationEntry` at the given offset.
654
0
    fn cie_from_offset(
655
0
        &self,
656
0
        bases: &BaseAddresses,
657
0
        offset: Self::Offset,
658
0
    ) -> Result<CommonInformationEntry<R>> {
659
0
        let offset = UnwindOffset::into(offset);
660
0
        let input = &mut self.section().clone();
661
0
        input.skip(offset)?;
662
0
        CommonInformationEntry::parse(bases, self, input)
663
0
    }
664
665
    /// Parse the `PartialFrameDescriptionEntry` at the given offset.
666
0
    fn partial_fde_from_offset<'bases>(
667
0
        &self,
668
0
        bases: &'bases BaseAddresses,
669
0
        offset: Self::Offset,
670
0
    ) -> Result<PartialFrameDescriptionEntry<'bases, Self, R>> {
671
0
        let offset = UnwindOffset::into(offset);
672
0
        let input = &mut self.section().clone();
673
0
        input.skip(offset)?;
674
0
        PartialFrameDescriptionEntry::parse_partial(self, bases, input)
675
0
    }
676
677
    /// Parse the `FrameDescriptionEntry` at the given offset.
678
0
    fn fde_from_offset<F>(
679
0
        &self,
680
0
        bases: &BaseAddresses,
681
0
        offset: Self::Offset,
682
0
        get_cie: F,
683
0
    ) -> Result<FrameDescriptionEntry<R>>
684
0
    where
685
0
        F: FnMut(&Self, &BaseAddresses, Self::Offset) -> Result<CommonInformationEntry<R>>,
686
    {
687
0
        let partial = self.partial_fde_from_offset(bases, offset)?;
688
0
        partial.parse(get_cie)
689
0
    }
690
691
    /// Find the `FrameDescriptionEntry` for the given address.
692
    ///
693
    /// If found, the FDE is returned.  If not found,
694
    /// `Err(gimli::Error::NoUnwindInfoForAddress)` is returned.
695
    /// If parsing fails, the error is returned.
696
    ///
697
    /// You must provide a function to get its associated CIE. See
698
    /// `PartialFrameDescriptionEntry::parse` for more information.
699
    ///
700
    /// Note: this iterates over all FDEs. If available, it is possible
701
    /// to do a binary search with `EhFrameHdr::fde_for_address` instead.
702
0
    fn fde_for_address<F>(
703
0
        &self,
704
0
        bases: &BaseAddresses,
705
0
        address: u64,
706
0
        mut get_cie: F,
707
0
    ) -> Result<FrameDescriptionEntry<R>>
708
0
    where
709
0
        F: FnMut(&Self, &BaseAddresses, Self::Offset) -> Result<CommonInformationEntry<R>>,
710
    {
711
0
        let mut entries = self.entries(bases);
712
0
        while let Some(entry) = entries.next()? {
713
0
            match entry {
714
0
                CieOrFde::Cie(_) => {}
715
0
                CieOrFde::Fde(partial) => {
716
0
                    let fde = partial.parse(&mut get_cie)?;
717
0
                    if fde.contains(address) {
718
0
                        return Ok(fde);
719
0
                    }
720
                }
721
            }
722
        }
723
0
        Err(Error::NoUnwindInfoForAddress)
724
0
    }
725
726
    /// Find the frame unwind information for the given address.
727
    ///
728
    /// If found, the unwind information is returned.  If not found,
729
    /// `Err(gimli::Error::NoUnwindInfoForAddress)` is returned. If parsing or
730
    /// CFI evaluation fails, the error is returned.
731
    ///
732
    /// ```
733
    /// use gimli::{BaseAddresses, EhFrame, EndianSlice, NativeEndian, UnwindContext,
734
    ///             UnwindSection};
735
    ///
736
    /// # fn foo() -> gimli::Result<()> {
737
    /// # let read_eh_frame_section = || unimplemented!();
738
    /// // Get the `.eh_frame` section from the object file. Alternatively,
739
    /// // use `EhFrame` with the `.eh_frame` section of the object file.
740
    /// let eh_frame = EhFrame::new(read_eh_frame_section(), NativeEndian);
741
    ///
742
    /// # let get_frame_pc = || unimplemented!();
743
    /// // Get the address of the PC for a frame you'd like to unwind.
744
    /// let address = get_frame_pc();
745
    ///
746
    /// // This context is reusable, which cuts down on heap allocations.
747
    /// let ctx = UnwindContext::new();
748
    ///
749
    /// // Optionally provide base addresses for any relative pointers. If a
750
    /// // base address isn't provided and a pointer is found that is relative to
751
    /// // it, we will return an `Err`.
752
    /// # let address_of_text_section_in_memory = unimplemented!();
753
    /// # let address_of_got_section_in_memory = unimplemented!();
754
    /// let bases = BaseAddresses::default()
755
    ///     .set_text(address_of_text_section_in_memory)
756
    ///     .set_got(address_of_got_section_in_memory);
757
    ///
758
    /// let unwind_info = eh_frame.unwind_info_for_address(
759
    ///     &bases,
760
    ///     &mut ctx,
761
    ///     address,
762
    ///     EhFrame::cie_from_offset,
763
    /// )?;
764
    ///
765
    /// # let do_stuff_with = |_| unimplemented!();
766
    /// do_stuff_with(unwind_info);
767
    /// # let _ = ctx;
768
    /// # unreachable!()
769
    /// # }
770
    /// ```
771
    #[inline]
772
0
    fn unwind_info_for_address<'ctx, F, S>(
773
0
        &self,
774
0
        bases: &BaseAddresses,
775
0
        ctx: &'ctx mut UnwindContext<R::Offset, S>,
776
0
        address: u64,
777
0
        get_cie: F,
778
0
    ) -> Result<&'ctx UnwindTableRow<R::Offset, S>>
779
0
    where
780
0
        F: FnMut(&Self, &BaseAddresses, Self::Offset) -> Result<CommonInformationEntry<R>>,
781
0
        S: UnwindContextStorage<R::Offset>,
782
    {
783
0
        let fde = self.fde_for_address(bases, address, get_cie)?;
784
0
        fde.unwind_info_for_address(self, bases, ctx, address)
785
0
    }
786
}
787
788
impl<R: Reader> _UnwindSectionPrivate<R> for DebugFrame<R> {
789
0
    fn section(&self) -> &R {
790
0
        &self.section
791
0
    }
792
793
0
    fn has_zero_terminator() -> bool {
794
0
        false
795
0
    }
796
797
0
    fn is_cie(format: Format, id: u64) -> bool {
798
0
        match format {
799
0
            Format::Dwarf32 => id == 0xffff_ffff,
800
0
            Format::Dwarf64 => id == 0xffff_ffff_ffff_ffff,
801
        }
802
0
    }
803
804
0
    fn cie_offset_encoding(format: Format) -> CieOffsetEncoding {
805
0
        match format {
806
0
            Format::Dwarf32 => CieOffsetEncoding::U32,
807
0
            Format::Dwarf64 => CieOffsetEncoding::U64,
808
        }
809
0
    }
810
811
0
    fn resolve_cie_offset(&self, _: R::Offset, offset: R::Offset) -> Option<R::Offset> {
812
0
        Some(offset)
813
0
    }
814
815
0
    fn has_address_and_segment_sizes(version: u8) -> bool {
816
0
        version == 4
817
0
    }
818
819
0
    fn address_size(&self) -> u8 {
820
0
        self.address_size
821
0
    }
822
823
0
    fn vendor(&self) -> Vendor {
824
0
        self.vendor
825
0
    }
826
}
827
828
impl<R: Reader> UnwindSection<R> for DebugFrame<R> {
829
    type Offset = DebugFrameOffset<R::Offset>;
830
}
831
832
impl<R: Reader> _UnwindSectionPrivate<R> for EhFrame<R> {
833
0
    fn section(&self) -> &R {
834
0
        &self.section
835
0
    }
836
837
0
    fn has_zero_terminator() -> bool {
838
0
        true
839
0
    }
840
841
0
    fn is_cie(_: Format, id: u64) -> bool {
842
0
        id == 0
843
0
    }
844
845
0
    fn cie_offset_encoding(_format: Format) -> CieOffsetEncoding {
846
        // `.eh_frame` offsets are always 4 bytes, regardless of the DWARF
847
        // format.
848
0
        CieOffsetEncoding::U32
849
0
    }
850
851
0
    fn resolve_cie_offset(&self, base: R::Offset, offset: R::Offset) -> Option<R::Offset> {
852
0
        base.checked_sub(offset)
853
0
    }
854
855
0
    fn has_address_and_segment_sizes(_version: u8) -> bool {
856
0
        false
857
0
    }
858
859
0
    fn address_size(&self) -> u8 {
860
0
        self.address_size
861
0
    }
862
863
0
    fn vendor(&self) -> Vendor {
864
0
        self.vendor
865
0
    }
866
}
867
868
impl<R: Reader> UnwindSection<R> for EhFrame<R> {
869
    type Offset = EhFrameOffset<R::Offset>;
870
}
871
872
/// Optional base addresses for the relative `DW_EH_PE_*` encoded pointers.
873
///
874
/// During CIE/FDE parsing, if a relative pointer is encountered for a base
875
/// address that is unknown, an Err will be returned.
876
///
877
/// ```
878
/// use gimli::BaseAddresses;
879
///
880
/// # fn foo() {
881
/// # let address_of_eh_frame_hdr_section_in_memory = unimplemented!();
882
/// # let address_of_eh_frame_section_in_memory = unimplemented!();
883
/// # let address_of_text_section_in_memory = unimplemented!();
884
/// # let address_of_got_section_in_memory = unimplemented!();
885
/// # let address_of_the_start_of_current_func = unimplemented!();
886
/// let bases = BaseAddresses::default()
887
///     .set_eh_frame_hdr(address_of_eh_frame_hdr_section_in_memory)
888
///     .set_eh_frame(address_of_eh_frame_section_in_memory)
889
///     .set_text(address_of_text_section_in_memory)
890
///     .set_got(address_of_got_section_in_memory);
891
/// # let _ = bases;
892
/// # }
893
/// ```
894
#[derive(Clone, Default, Debug, PartialEq, Eq)]
895
pub struct BaseAddresses {
896
    /// The base addresses to use for pointers in the `.eh_frame_hdr` section.
897
    pub eh_frame_hdr: SectionBaseAddresses,
898
899
    /// The base addresses to use for pointers in the `.eh_frame` section.
900
    pub eh_frame: SectionBaseAddresses,
901
}
902
903
/// Optional base addresses for the relative `DW_EH_PE_*` encoded pointers
904
/// in a particular section.
905
///
906
/// See `BaseAddresses` for methods that are helpful in setting these addresses.
907
#[derive(Clone, Default, Debug, PartialEq, Eq)]
908
pub struct SectionBaseAddresses {
909
    /// The address of the section containing the pointer.
910
    pub section: Option<u64>,
911
912
    /// The base address for text relative pointers.
913
    /// This is generally the address of the `.text` section.
914
    pub text: Option<u64>,
915
916
    /// The base address for data relative pointers.
917
    ///
918
    /// For pointers in the `.eh_frame_hdr` section, this is the address
919
    /// of the `.eh_frame_hdr` section
920
    ///
921
    /// For pointers in the `.eh_frame` section, this is generally the
922
    /// global pointer, such as the address of the `.got` section.
923
    pub data: Option<u64>,
924
}
925
926
impl BaseAddresses {
927
    /// Set the `.eh_frame_hdr` section base address.
928
    #[inline]
929
0
    pub fn set_eh_frame_hdr(mut self, addr: u64) -> Self {
930
0
        self.eh_frame_hdr.section = Some(addr);
931
0
        self.eh_frame_hdr.data = Some(addr);
932
0
        self
933
0
    }
934
935
    /// Set the `.eh_frame` section base address.
936
    #[inline]
937
0
    pub fn set_eh_frame(mut self, addr: u64) -> Self {
938
0
        self.eh_frame.section = Some(addr);
939
0
        self
940
0
    }
941
942
    /// Set the `.text` section base address.
943
    #[inline]
944
0
    pub fn set_text(mut self, addr: u64) -> Self {
945
0
        self.eh_frame_hdr.text = Some(addr);
946
0
        self.eh_frame.text = Some(addr);
947
0
        self
948
0
    }
949
950
    /// Set the `.got` section base address.
951
    #[inline]
952
0
    pub fn set_got(mut self, addr: u64) -> Self {
953
0
        self.eh_frame.data = Some(addr);
954
0
        self
955
0
    }
956
}
957
958
/// An iterator over CIE and FDE entries in a `.debug_frame` or `.eh_frame`
959
/// section.
960
///
961
/// Some pointers may be encoded relative to various base addresses. Use the
962
/// [`BaseAddresses`](./struct.BaseAddresses.html) parameter to provide them. By
963
/// default, none are provided. If a relative pointer is encountered for a base
964
/// address that is unknown, an `Err` will be returned and iteration will abort.
965
///
966
/// Can be [used with
967
/// `FallibleIterator`](./index.html#using-with-fallibleiterator).
968
///
969
/// ```
970
/// use gimli::{BaseAddresses, EhFrame, EndianSlice, NativeEndian, UnwindSection};
971
///
972
/// # fn foo() -> gimli::Result<()> {
973
/// # let read_eh_frame_somehow = || unimplemented!();
974
/// let eh_frame = EhFrame::new(read_eh_frame_somehow(), NativeEndian);
975
///
976
/// # let address_of_eh_frame_hdr_section_in_memory = unimplemented!();
977
/// # let address_of_eh_frame_section_in_memory = unimplemented!();
978
/// # let address_of_text_section_in_memory = unimplemented!();
979
/// # let address_of_got_section_in_memory = unimplemented!();
980
/// # let address_of_the_start_of_current_func = unimplemented!();
981
/// // Provide base addresses for relative pointers.
982
/// let bases = BaseAddresses::default()
983
///     .set_eh_frame_hdr(address_of_eh_frame_hdr_section_in_memory)
984
///     .set_eh_frame(address_of_eh_frame_section_in_memory)
985
///     .set_text(address_of_text_section_in_memory)
986
///     .set_got(address_of_got_section_in_memory);
987
///
988
/// let mut entries = eh_frame.entries(&bases);
989
///
990
/// # let do_stuff_with = |_| unimplemented!();
991
/// while let Some(entry) = entries.next()? {
992
///     do_stuff_with(entry)
993
/// }
994
/// # unreachable!()
995
/// # }
996
/// ```
997
#[derive(Clone, Debug)]
998
pub struct CfiEntriesIter<'bases, Section, R>
999
where
1000
    R: Reader,
1001
    Section: UnwindSection<R>,
1002
{
1003
    section: Section,
1004
    bases: &'bases BaseAddresses,
1005
    input: R,
1006
}
1007
1008
impl<'bases, Section, R> CfiEntriesIter<'bases, Section, R>
1009
where
1010
    R: Reader,
1011
    Section: UnwindSection<R>,
1012
{
1013
    /// Advance the iterator to the next entry.
1014
0
    pub fn next(&mut self) -> Result<Option<CieOrFde<'bases, Section, R>>> {
1015
        loop {
1016
0
            if self.input.is_empty() {
1017
0
                return Ok(None);
1018
0
            }
1019
1020
0
            match parse_cfi_entry(self.bases, &self.section, &mut self.input) {
1021
0
                Ok(Some(entry)) => return Ok(Some(entry)),
1022
0
                Err(e) => {
1023
0
                    self.input.empty();
1024
0
                    return Err(e);
1025
                }
1026
                Ok(None) => {
1027
0
                    if Section::has_zero_terminator() {
1028
0
                        self.input.empty();
1029
0
                        return Ok(None);
1030
0
                    }
1031
1032
                    // Hack: If we get to here, then we're reading `.debug_frame` and
1033
                    // encountered a length of 0. This is a compiler or linker bug
1034
                    // (originally seen for NASM, fixed in 2.15rc9).
1035
                    // Skip this value and try again.
1036
0
                    continue;
1037
                }
1038
            }
1039
        }
1040
0
    }
1041
}
1042
1043
#[cfg(feature = "fallible-iterator")]
1044
impl<'bases, Section, R> fallible_iterator::FallibleIterator for CfiEntriesIter<'bases, Section, R>
1045
where
1046
    R: Reader,
1047
    Section: UnwindSection<R>,
1048
{
1049
    type Item = CieOrFde<'bases, Section, R>;
1050
    type Error = Error;
1051
1052
    fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
1053
        CfiEntriesIter::next(self)
1054
    }
1055
}
1056
1057
/// Either a `CommonInformationEntry` (CIE) or a `FrameDescriptionEntry` (FDE).
1058
#[derive(Clone, Debug, PartialEq, Eq)]
1059
pub enum CieOrFde<'bases, Section, R>
1060
where
1061
    R: Reader,
1062
    Section: UnwindSection<R>,
1063
{
1064
    /// This CFI entry is a `CommonInformationEntry`.
1065
    Cie(CommonInformationEntry<R>),
1066
    /// This CFI entry is a `FrameDescriptionEntry`, however fully parsing it
1067
    /// requires parsing its CIE first, so it is left in a partially parsed
1068
    /// state.
1069
    Fde(PartialFrameDescriptionEntry<'bases, Section, R>),
1070
}
1071
1072
0
fn parse_cfi_entry<'bases, Section, R>(
1073
0
    bases: &'bases BaseAddresses,
1074
0
    section: &Section,
1075
0
    input: &mut R,
1076
0
) -> Result<Option<CieOrFde<'bases, Section, R>>>
1077
0
where
1078
0
    R: Reader,
1079
0
    Section: UnwindSection<R>,
1080
{
1081
0
    let offset = input.offset_from(section.section());
1082
0
    let (length, format) = input.read_initial_length()?;
1083
0
    if length.into_u64() == 0 {
1084
0
        return Ok(None);
1085
0
    }
1086
1087
0
    let mut rest = input.split(length)?;
1088
0
    let cie_offset_base = rest.offset_from(section.section());
1089
0
    let cie_id_or_offset = match Section::cie_offset_encoding(format) {
1090
0
        CieOffsetEncoding::U32 => rest.read_u32().map(u64::from)?,
1091
0
        CieOffsetEncoding::U64 => rest.read_u64()?,
1092
    };
1093
1094
0
    if Section::is_cie(format, cie_id_or_offset) {
1095
0
        let cie = CommonInformationEntry::parse_rest(offset, length, format, bases, section, rest)?;
1096
0
        Ok(Some(CieOrFde::Cie(cie)))
1097
    } else {
1098
0
        let cie_offset = R::Offset::from_u64(cie_id_or_offset)?;
1099
0
        let cie_offset = match section.resolve_cie_offset(cie_offset_base, cie_offset) {
1100
0
            None => return Err(Error::OffsetOutOfBounds),
1101
0
            Some(cie_offset) => cie_offset,
1102
        };
1103
1104
0
        let fde = PartialFrameDescriptionEntry {
1105
0
            offset,
1106
0
            length,
1107
0
            format,
1108
0
            cie_offset: cie_offset.into(),
1109
0
            rest,
1110
0
            section: section.clone(),
1111
0
            bases,
1112
0
        };
1113
1114
0
        Ok(Some(CieOrFde::Fde(fde)))
1115
    }
1116
0
}
1117
1118
/// We support the z-style augmentation [defined by `.eh_frame`][ehframe].
1119
///
1120
/// [ehframe]: https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
1121
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
1122
pub struct Augmentation {
1123
    /// > A 'L' may be present at any position after the first character of the
1124
    /// > string. This character may only be present if 'z' is the first character
1125
    /// > of the string. If present, it indicates the presence of one argument in
1126
    /// > the Augmentation Data of the CIE, and a corresponding argument in the
1127
    /// > Augmentation Data of the FDE. The argument in the Augmentation Data of
1128
    /// > the CIE is 1-byte and represents the pointer encoding used for the
1129
    /// > argument in the Augmentation Data of the FDE, which is the address of a
1130
    /// > language-specific data area (LSDA). The size of the LSDA pointer is
1131
    /// > specified by the pointer encoding used.
1132
    lsda: Option<constants::DwEhPe>,
1133
1134
    /// > A 'P' may be present at any position after the first character of the
1135
    /// > string. This character may only be present if 'z' is the first character
1136
    /// > of the string. If present, it indicates the presence of two arguments in
1137
    /// > the Augmentation Data of the CIE. The first argument is 1-byte and
1138
    /// > represents the pointer encoding used for the second argument, which is
1139
    /// > the address of a personality routine handler. The size of the
1140
    /// > personality routine pointer is specified by the pointer encoding used.
1141
    personality: Option<(constants::DwEhPe, Pointer)>,
1142
1143
    /// > A 'R' may be present at any position after the first character of the
1144
    /// > string. This character may only be present if 'z' is the first character
1145
    /// > of the string. If present, The Augmentation Data shall include a 1 byte
1146
    /// > argument that represents the pointer encoding for the address pointers
1147
    /// > used in the FDE.
1148
    fde_address_encoding: Option<constants::DwEhPe>,
1149
1150
    /// True if this CIE's FDEs are trampolines for signal handlers.
1151
    is_signal_trampoline: bool,
1152
}
1153
1154
impl Augmentation {
1155
0
    fn parse<Section, R>(
1156
0
        augmentation_str: &mut R,
1157
0
        bases: &BaseAddresses,
1158
0
        address_size: u8,
1159
0
        section: &Section,
1160
0
        input: &mut R,
1161
0
    ) -> Result<Augmentation>
1162
0
    where
1163
0
        R: Reader,
1164
0
        Section: UnwindSection<R>,
1165
    {
1166
0
        debug_assert!(
1167
0
            !augmentation_str.is_empty(),
1168
            "Augmentation::parse should only be called if we have an augmentation"
1169
        );
1170
1171
0
        let mut augmentation = Augmentation::default();
1172
1173
0
        let mut parsed_first = false;
1174
0
        let mut data = None;
1175
1176
0
        while !augmentation_str.is_empty() {
1177
0
            let ch = augmentation_str.read_u8()?;
1178
0
            match ch {
1179
                b'z' => {
1180
0
                    if parsed_first {
1181
0
                        return Err(Error::UnknownAugmentation);
1182
0
                    }
1183
1184
0
                    let augmentation_length = input.read_uleb128().and_then(R::Offset::from_u64)?;
1185
0
                    data = Some(input.split(augmentation_length)?);
1186
                }
1187
                b'L' => {
1188
0
                    let rest = data.as_mut().ok_or(Error::UnknownAugmentation)?;
1189
0
                    let encoding = parse_pointer_encoding(rest)?;
1190
0
                    augmentation.lsda = Some(encoding);
1191
                }
1192
                b'P' => {
1193
0
                    let rest = data.as_mut().ok_or(Error::UnknownAugmentation)?;
1194
0
                    let encoding = parse_pointer_encoding(rest)?;
1195
0
                    let parameters = PointerEncodingParameters {
1196
0
                        bases: &bases.eh_frame,
1197
0
                        func_base: None,
1198
0
                        address_size,
1199
0
                        section: section.section(),
1200
0
                    };
1201
1202
0
                    let personality = parse_encoded_pointer(encoding, &parameters, rest)?;
1203
0
                    augmentation.personality = Some((encoding, personality));
1204
                }
1205
                b'R' => {
1206
0
                    let rest = data.as_mut().ok_or(Error::UnknownAugmentation)?;
1207
0
                    let encoding = parse_pointer_encoding(rest)?;
1208
0
                    augmentation.fde_address_encoding = Some(encoding);
1209
                }
1210
0
                b'S' => augmentation.is_signal_trampoline = true,
1211
0
                _ => return Err(Error::UnknownAugmentation),
1212
            }
1213
1214
0
            parsed_first = true;
1215
        }
1216
1217
0
        Ok(augmentation)
1218
0
    }
1219
}
1220
1221
/// Parsed augmentation data for a `FrameDescriptEntry`.
1222
#[derive(Clone, Debug, Default, PartialEq, Eq)]
1223
struct AugmentationData {
1224
    lsda: Option<Pointer>,
1225
}
1226
1227
impl AugmentationData {
1228
0
    fn parse<R: Reader>(
1229
0
        augmentation: &Augmentation,
1230
0
        encoding_parameters: &PointerEncodingParameters<'_, R>,
1231
0
        input: &mut R,
1232
0
    ) -> Result<AugmentationData> {
1233
        // In theory, we should be iterating over the original augmentation
1234
        // string, interpreting each character, and reading the appropriate bits
1235
        // out of the augmentation data as we go. However, the only character
1236
        // that defines augmentation data in the FDE is the 'L' character, so we
1237
        // can just check for its presence directly.
1238
1239
0
        let aug_data_len = input.read_uleb128().and_then(R::Offset::from_u64)?;
1240
0
        let rest = &mut input.split(aug_data_len)?;
1241
0
        let mut augmentation_data = AugmentationData::default();
1242
0
        if let Some(encoding) = augmentation.lsda {
1243
0
            let lsda = parse_encoded_pointer(encoding, encoding_parameters, rest)?;
1244
0
            augmentation_data.lsda = Some(lsda);
1245
0
        }
1246
0
        Ok(augmentation_data)
1247
0
    }
1248
}
1249
1250
/// > A Common Information Entry holds information that is shared among many
1251
/// > Frame Description Entries. There is at least one CIE in every non-empty
1252
/// > `.debug_frame` section.
1253
#[derive(Clone, Debug, PartialEq, Eq)]
1254
pub struct CommonInformationEntry<R, Offset = <R as Reader>::Offset>
1255
where
1256
    R: Reader<Offset = Offset>,
1257
    Offset: ReaderOffset,
1258
{
1259
    /// The offset of this entry from the start of its containing section.
1260
    offset: Offset,
1261
1262
    /// > A constant that gives the number of bytes of the CIE structure, not
1263
    /// > including the length field itself (see Section 7.2.2). The size of the
1264
    /// > length field plus the value of length must be an integral multiple of
1265
    /// > the address size.
1266
    length: Offset,
1267
1268
    format: Format,
1269
1270
    /// > A version number (see Section 7.23). This number is specific to the
1271
    /// > call frame information and is independent of the DWARF version number.
1272
    version: u8,
1273
1274
    /// The parsed augmentation, if any.
1275
    augmentation: Option<Augmentation>,
1276
1277
    /// > The size of a target address in this CIE and any FDEs that use it, in
1278
    /// > bytes. If a compilation unit exists for this frame, its address size
1279
    /// > must match the address size here.
1280
    address_size: u8,
1281
1282
    /// "A constant that is factored out of all advance location instructions
1283
    /// (see Section 6.4.2.1)."
1284
    code_alignment_factor: u64,
1285
1286
    /// > A constant that is factored out of certain offset instructions (see
1287
    /// > below). The resulting value is (operand * data_alignment_factor).
1288
    data_alignment_factor: i64,
1289
1290
    /// > An unsigned LEB128 constant that indicates which column in the rule
1291
    /// > table represents the return address of the function. Note that this
1292
    /// > column might not correspond to an actual machine register.
1293
    return_address_register: Register,
1294
1295
    /// > A sequence of rules that are interpreted to create the initial setting
1296
    /// > of each column in the table.
1297
    ///
1298
    /// > The default rule for all columns before interpretation of the initial
1299
    /// > instructions is the undefined rule. However, an ABI authoring body or a
1300
    /// > compilation system authoring body may specify an alternate default
1301
    /// > value for any or all columns.
1302
    ///
1303
    /// This is followed by `DW_CFA_nop` padding until the end of `length` bytes
1304
    /// in the input.
1305
    initial_instructions: R,
1306
}
1307
1308
impl<R: Reader> CommonInformationEntry<R> {
1309
0
    fn parse<Section: UnwindSection<R>>(
1310
0
        bases: &BaseAddresses,
1311
0
        section: &Section,
1312
0
        input: &mut R,
1313
0
    ) -> Result<CommonInformationEntry<R>> {
1314
0
        match parse_cfi_entry(bases, section, input)? {
1315
0
            Some(CieOrFde::Cie(cie)) => Ok(cie),
1316
0
            Some(CieOrFde::Fde(_)) => Err(Error::NotCieId),
1317
0
            None => Err(Error::NoEntryAtGivenOffset),
1318
        }
1319
0
    }
1320
1321
0
    fn parse_rest<Section: UnwindSection<R>>(
1322
0
        offset: R::Offset,
1323
0
        length: R::Offset,
1324
0
        format: Format,
1325
0
        bases: &BaseAddresses,
1326
0
        section: &Section,
1327
0
        mut rest: R,
1328
0
    ) -> Result<CommonInformationEntry<R>> {
1329
0
        let version = rest.read_u8()?;
1330
1331
        // Version 1 of `.debug_frame` corresponds to DWARF 2, and then for
1332
        // DWARF 3 and 4, I think they decided to just match the standard's
1333
        // version.
1334
0
        match version {
1335
0
            1 | 3 | 4 => (),
1336
0
            _ => return Err(Error::UnknownVersion(u64::from(version))),
1337
        }
1338
1339
0
        let mut augmentation_string = rest.read_null_terminated_slice()?;
1340
1341
0
        let address_size = if Section::has_address_and_segment_sizes(version) {
1342
0
            let address_size = rest.read_address_size()?;
1343
0
            let segment_size = rest.read_u8()?;
1344
0
            if segment_size != 0 {
1345
0
                return Err(Error::UnsupportedSegmentSize);
1346
0
            }
1347
0
            address_size
1348
        } else {
1349
0
            section.address_size()
1350
        };
1351
1352
0
        let code_alignment_factor = rest.read_uleb128()?;
1353
0
        let data_alignment_factor = rest.read_sleb128()?;
1354
1355
0
        let return_address_register = if version == 1 {
1356
0
            Register(rest.read_u8()?.into())
1357
        } else {
1358
0
            rest.read_uleb128().and_then(Register::from_u64)?
1359
        };
1360
1361
0
        let augmentation = if augmentation_string.is_empty() {
1362
0
            None
1363
        } else {
1364
0
            Some(Augmentation::parse(
1365
0
                &mut augmentation_string,
1366
0
                bases,
1367
0
                address_size,
1368
0
                section,
1369
0
                &mut rest,
1370
0
            )?)
1371
        };
1372
1373
0
        let entry = CommonInformationEntry {
1374
0
            offset,
1375
0
            length,
1376
0
            format,
1377
0
            version,
1378
0
            augmentation,
1379
0
            address_size,
1380
0
            code_alignment_factor,
1381
0
            data_alignment_factor,
1382
0
            return_address_register,
1383
0
            initial_instructions: rest,
1384
0
        };
1385
1386
0
        Ok(entry)
1387
0
    }
1388
}
1389
1390
/// # Signal Safe Methods
1391
///
1392
/// These methods are guaranteed not to allocate, acquire locks, or perform any
1393
/// other signal-unsafe operations.
1394
impl<R: Reader> CommonInformationEntry<R> {
1395
    /// Get the offset of this entry from the start of its containing section.
1396
0
    pub fn offset(&self) -> R::Offset {
1397
0
        self.offset
1398
0
    }
1399
1400
    /// Return the encoding parameters for this CIE.
1401
0
    pub fn encoding(&self) -> Encoding {
1402
0
        Encoding {
1403
0
            format: self.format,
1404
0
            version: u16::from(self.version),
1405
0
            address_size: self.address_size,
1406
0
        }
1407
0
    }
1408
1409
    /// The size of addresses (in bytes) in this CIE.
1410
0
    pub fn address_size(&self) -> u8 {
1411
0
        self.address_size
1412
0
    }
1413
1414
    /// Iterate over this CIE's initial instructions.
1415
    ///
1416
    /// Can be [used with
1417
    /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
1418
0
    pub fn instructions<'a, Section>(
1419
0
        &self,
1420
0
        section: &'a Section,
1421
0
        bases: &'a BaseAddresses,
1422
0
    ) -> CallFrameInstructionIter<'a, R>
1423
0
    where
1424
0
        Section: UnwindSection<R>,
1425
    {
1426
0
        CallFrameInstructionIter {
1427
0
            input: self.initial_instructions.clone(),
1428
0
            address_encoding: None,
1429
0
            parameters: PointerEncodingParameters {
1430
0
                bases: &bases.eh_frame,
1431
0
                func_base: None,
1432
0
                address_size: self.address_size,
1433
0
                section: section.section(),
1434
0
            },
1435
0
            vendor: section.vendor(),
1436
0
        }
1437
0
    }
1438
1439
    /// > A constant that gives the number of bytes of the CIE structure, not
1440
    /// > including the length field itself (see Section 7.2.2). The size of the
1441
    /// > length field plus the value of length must be an integral multiple of
1442
    /// > the address size.
1443
0
    pub fn entry_len(&self) -> R::Offset {
1444
0
        self.length
1445
0
    }
1446
1447
    /// > A version number (see Section 7.23). This number is specific to the
1448
    /// > call frame information and is independent of the DWARF version number.
1449
0
    pub fn version(&self) -> u8 {
1450
0
        self.version
1451
0
    }
1452
1453
    /// Get the augmentation data, if any exists.
1454
    ///
1455
    /// The only augmentation understood by `gimli` is that which is defined by
1456
    /// `.eh_frame`.
1457
0
    pub fn augmentation(&self) -> Option<&Augmentation> {
1458
0
        self.augmentation.as_ref()
1459
0
    }
1460
1461
    /// True if this CIE's FDEs have a LSDA.
1462
0
    pub fn has_lsda(&self) -> bool {
1463
0
        self.augmentation.map_or(false, |a| a.lsda.is_some())
1464
0
    }
1465
1466
    /// Return the encoding of the LSDA address for this CIE's FDEs.
1467
0
    pub fn lsda_encoding(&self) -> Option<constants::DwEhPe> {
1468
0
        self.augmentation.and_then(|a| a.lsda)
1469
0
    }
1470
1471
    /// Return the encoding and address of the personality routine handler
1472
    /// for this CIE's FDEs.
1473
0
    pub fn personality_with_encoding(&self) -> Option<(constants::DwEhPe, Pointer)> {
1474
0
        self.augmentation.as_ref().and_then(|a| a.personality)
1475
0
    }
1476
1477
    /// Return the address of the personality routine handler
1478
    /// for this CIE's FDEs.
1479
0
    pub fn personality(&self) -> Option<Pointer> {
1480
0
        self.augmentation
1481
0
            .as_ref()
1482
0
            .and_then(|a| a.personality)
1483
0
            .map(|(_, p)| p)
1484
0
    }
1485
1486
    /// Return the encoding of the addresses for this CIE's FDEs.
1487
0
    pub fn fde_address_encoding(&self) -> Option<constants::DwEhPe> {
1488
0
        self.augmentation.and_then(|a| a.fde_address_encoding)
1489
0
    }
1490
1491
    /// True if this CIE's FDEs are trampolines for signal handlers.
1492
0
    pub fn is_signal_trampoline(&self) -> bool {
1493
0
        self.augmentation.map_or(false, |a| a.is_signal_trampoline)
1494
0
    }
1495
1496
    /// > A constant that is factored out of all advance location instructions
1497
    /// > (see Section 6.4.2.1).
1498
0
    pub fn code_alignment_factor(&self) -> u64 {
1499
0
        self.code_alignment_factor
1500
0
    }
1501
1502
    /// > A constant that is factored out of certain offset instructions (see
1503
    /// > below). The resulting value is (operand * data_alignment_factor).
1504
0
    pub fn data_alignment_factor(&self) -> i64 {
1505
0
        self.data_alignment_factor
1506
0
    }
1507
1508
    /// > An unsigned ... constant that indicates which column in the rule
1509
    /// > table represents the return address of the function. Note that this
1510
    /// > column might not correspond to an actual machine register.
1511
0
    pub fn return_address_register(&self) -> Register {
1512
0
        self.return_address_register
1513
0
    }
1514
}
1515
1516
/// A partially parsed `FrameDescriptionEntry`.
1517
///
1518
/// Fully parsing this FDE requires first parsing its CIE.
1519
#[derive(Clone, Debug, PartialEq, Eq)]
1520
pub struct PartialFrameDescriptionEntry<'bases, Section, R>
1521
where
1522
    R: Reader,
1523
    Section: UnwindSection<R>,
1524
{
1525
    offset: R::Offset,
1526
    length: R::Offset,
1527
    format: Format,
1528
    cie_offset: Section::Offset,
1529
    rest: R,
1530
    section: Section,
1531
    bases: &'bases BaseAddresses,
1532
}
1533
1534
impl<'bases, Section, R> PartialFrameDescriptionEntry<'bases, Section, R>
1535
where
1536
    R: Reader,
1537
    Section: UnwindSection<R>,
1538
{
1539
0
    fn parse_partial(
1540
0
        section: &Section,
1541
0
        bases: &'bases BaseAddresses,
1542
0
        input: &mut R,
1543
0
    ) -> Result<PartialFrameDescriptionEntry<'bases, Section, R>> {
1544
0
        match parse_cfi_entry(bases, section, input)? {
1545
0
            Some(CieOrFde::Cie(_)) => Err(Error::NotFdePointer),
1546
0
            Some(CieOrFde::Fde(partial)) => Ok(partial),
1547
0
            None => Err(Error::NoEntryAtGivenOffset),
1548
        }
1549
0
    }
1550
1551
    /// Fully parse this FDE.
1552
    ///
1553
    /// You must provide a function get its associated CIE (either by parsing it
1554
    /// on demand, or looking it up in some table mapping offsets to CIEs that
1555
    /// you've already parsed, etc.)
1556
0
    pub fn parse<F>(&self, get_cie: F) -> Result<FrameDescriptionEntry<R>>
1557
0
    where
1558
0
        F: FnMut(&Section, &BaseAddresses, Section::Offset) -> Result<CommonInformationEntry<R>>,
1559
    {
1560
0
        FrameDescriptionEntry::parse_rest(
1561
0
            self.offset,
1562
0
            self.length,
1563
0
            self.format,
1564
0
            self.cie_offset,
1565
0
            self.rest.clone(),
1566
0
            &self.section,
1567
0
            self.bases,
1568
0
            get_cie,
1569
        )
1570
0
    }
1571
1572
    /// Get the offset of this entry from the start of its containing section.
1573
0
    pub fn offset(&self) -> R::Offset {
1574
0
        self.offset
1575
0
    }
1576
1577
    /// Get the offset of this FDE's CIE.
1578
0
    pub fn cie_offset(&self) -> Section::Offset {
1579
0
        self.cie_offset
1580
0
    }
1581
1582
    /// > A constant that gives the number of bytes of the header and
1583
    /// > instruction stream for this function, not including the length field
1584
    /// > itself (see Section 7.2.2). The size of the length field plus the value
1585
    /// > of length must be an integral multiple of the address size.
1586
0
    pub fn entry_len(&self) -> R::Offset {
1587
0
        self.length
1588
0
    }
1589
}
1590
1591
/// A `FrameDescriptionEntry` is a set of CFA instructions for an address range.
1592
#[derive(Clone, Debug, PartialEq, Eq)]
1593
pub struct FrameDescriptionEntry<R, Offset = <R as Reader>::Offset>
1594
where
1595
    R: Reader<Offset = Offset>,
1596
    Offset: ReaderOffset,
1597
{
1598
    /// The start of this entry within its containing section.
1599
    offset: Offset,
1600
1601
    /// > A constant that gives the number of bytes of the header and
1602
    /// > instruction stream for this function, not including the length field
1603
    /// > itself (see Section 7.2.2). The size of the length field plus the value
1604
    /// > of length must be an integral multiple of the address size.
1605
    length: Offset,
1606
1607
    format: Format,
1608
1609
    /// "A constant offset into the .debug_frame section that denotes the CIE
1610
    /// that is associated with this FDE."
1611
    ///
1612
    /// This is the CIE at that offset.
1613
    cie: CommonInformationEntry<R, Offset>,
1614
1615
    /// > The address of the first location associated with this table entry. If
1616
    /// > the segment_size field of this FDE's CIE is non-zero, the initial
1617
    /// > location is preceded by a segment selector of the given length.
1618
    initial_address: u64,
1619
1620
    /// "The number of bytes of program instructions described by this entry."
1621
    address_range: u64,
1622
1623
    /// The parsed augmentation data, if we have any.
1624
    augmentation: Option<AugmentationData>,
1625
1626
    /// "A sequence of table defining instructions that are described below."
1627
    ///
1628
    /// This is followed by `DW_CFA_nop` padding until `length` bytes of the
1629
    /// input are consumed.
1630
    instructions: R,
1631
}
1632
1633
impl<R: Reader> FrameDescriptionEntry<R> {
1634
0
    fn parse_rest<Section, F>(
1635
0
        offset: R::Offset,
1636
0
        length: R::Offset,
1637
0
        format: Format,
1638
0
        cie_pointer: Section::Offset,
1639
0
        mut rest: R,
1640
0
        section: &Section,
1641
0
        bases: &BaseAddresses,
1642
0
        mut get_cie: F,
1643
0
    ) -> Result<FrameDescriptionEntry<R>>
1644
0
    where
1645
0
        Section: UnwindSection<R>,
1646
0
        F: FnMut(&Section, &BaseAddresses, Section::Offset) -> Result<CommonInformationEntry<R>>,
1647
    {
1648
0
        let cie = get_cie(section, bases, cie_pointer)?;
1649
1650
0
        let mut parameters = PointerEncodingParameters {
1651
0
            bases: &bases.eh_frame,
1652
0
            func_base: None,
1653
0
            address_size: cie.address_size,
1654
0
            section: section.section(),
1655
0
        };
1656
1657
0
        let (initial_address, address_range) = Self::parse_addresses(&mut rest, &cie, &parameters)?;
1658
0
        parameters.func_base = Some(initial_address);
1659
1660
0
        let aug_data = if let Some(ref augmentation) = cie.augmentation {
1661
0
            Some(AugmentationData::parse(
1662
0
                augmentation,
1663
0
                &parameters,
1664
0
                &mut rest,
1665
0
            )?)
1666
        } else {
1667
0
            None
1668
        };
1669
1670
0
        let entry = FrameDescriptionEntry {
1671
0
            offset,
1672
0
            length,
1673
0
            format,
1674
0
            cie,
1675
0
            initial_address,
1676
0
            address_range,
1677
0
            augmentation: aug_data,
1678
0
            instructions: rest,
1679
0
        };
1680
1681
0
        Ok(entry)
1682
0
    }
1683
1684
0
    fn parse_addresses(
1685
0
        input: &mut R,
1686
0
        cie: &CommonInformationEntry<R>,
1687
0
        parameters: &PointerEncodingParameters<'_, R>,
1688
0
    ) -> Result<(u64, u64)> {
1689
0
        let encoding = cie.augmentation().and_then(|a| a.fde_address_encoding);
1690
0
        if let Some(encoding) = encoding {
1691
            // Ignore indirection.
1692
0
            let initial_address = parse_encoded_pointer(encoding, parameters, input)?.pointer();
1693
0
            let address_range = parse_encoded_value(encoding, parameters, input)?;
1694
0
            Ok((initial_address, address_range))
1695
        } else {
1696
0
            let initial_address = input.read_address(cie.address_size)?;
1697
0
            let address_range = input.read_address(cie.address_size)?;
1698
0
            Ok((initial_address, address_range))
1699
        }
1700
0
    }
1701
1702
    /// Return the table of unwind information for this FDE.
1703
    #[inline]
1704
0
    pub fn rows<'a, 'ctx, Section, S>(
1705
0
        &self,
1706
0
        section: &'a Section,
1707
0
        bases: &'a BaseAddresses,
1708
0
        ctx: &'ctx mut UnwindContext<R::Offset, S>,
1709
0
    ) -> Result<UnwindTable<'a, 'ctx, R, S>>
1710
0
    where
1711
0
        Section: UnwindSection<R>,
1712
0
        S: UnwindContextStorage<R::Offset>,
1713
    {
1714
0
        UnwindTable::new(section, bases, ctx, self)
1715
0
    }
1716
1717
    /// Find the frame unwind information for the given address.
1718
    ///
1719
    /// If found, the unwind information is returned along with the reset
1720
    /// context in the form `Ok((unwind_info, context))`. If not found,
1721
    /// `Err(gimli::Error::NoUnwindInfoForAddress)` is returned. If parsing or
1722
    /// CFI evaluation fails, the error is returned.
1723
0
    pub fn unwind_info_for_address<'ctx, Section, S>(
1724
0
        &self,
1725
0
        section: &Section,
1726
0
        bases: &BaseAddresses,
1727
0
        ctx: &'ctx mut UnwindContext<R::Offset, S>,
1728
0
        address: u64,
1729
0
    ) -> Result<&'ctx UnwindTableRow<R::Offset, S>>
1730
0
    where
1731
0
        Section: UnwindSection<R>,
1732
0
        S: UnwindContextStorage<R::Offset>,
1733
    {
1734
0
        let mut table = self.rows(section, bases, ctx)?;
1735
0
        while let Some(row) = table.next_row()? {
1736
0
            if row.contains(address) {
1737
0
                return Ok(table.ctx.row());
1738
0
            }
1739
        }
1740
0
        Err(Error::NoUnwindInfoForAddress)
1741
0
    }
1742
}
1743
1744
/// # Signal Safe Methods
1745
///
1746
/// These methods are guaranteed not to allocate, acquire locks, or perform any
1747
/// other signal-unsafe operations.
1748
#[allow(clippy::len_without_is_empty)]
1749
impl<R: Reader> FrameDescriptionEntry<R> {
1750
    /// Get the offset of this entry from the start of its containing section.
1751
0
    pub fn offset(&self) -> R::Offset {
1752
0
        self.offset
1753
0
    }
1754
1755
    /// Get a reference to this FDE's CIE.
1756
0
    pub fn cie(&self) -> &CommonInformationEntry<R> {
1757
0
        &self.cie
1758
0
    }
1759
1760
    /// > A constant that gives the number of bytes of the header and
1761
    /// > instruction stream for this function, not including the length field
1762
    /// > itself (see Section 7.2.2). The size of the length field plus the value
1763
    /// > of length must be an integral multiple of the address size.
1764
0
    pub fn entry_len(&self) -> R::Offset {
1765
0
        self.length
1766
0
    }
1767
1768
    /// Iterate over this FDE's instructions.
1769
    ///
1770
    /// Will not include the CIE's initial instructions, if you want those do
1771
    /// `fde.cie().instructions()` first.
1772
    ///
1773
    /// Can be [used with
1774
    /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
1775
0
    pub fn instructions<'a, Section>(
1776
0
        &self,
1777
0
        section: &'a Section,
1778
0
        bases: &'a BaseAddresses,
1779
0
    ) -> CallFrameInstructionIter<'a, R>
1780
0
    where
1781
0
        Section: UnwindSection<R>,
1782
    {
1783
        CallFrameInstructionIter {
1784
0
            input: self.instructions.clone(),
1785
0
            address_encoding: self.cie.augmentation().and_then(|a| a.fde_address_encoding),
1786
0
            parameters: PointerEncodingParameters {
1787
0
                bases: &bases.eh_frame,
1788
0
                func_base: None,
1789
0
                address_size: self.cie.address_size,
1790
0
                section: section.section(),
1791
0
            },
1792
0
            vendor: section.vendor(),
1793
        }
1794
0
    }
1795
1796
    /// The first address for which this entry has unwind information for.
1797
0
    pub fn initial_address(&self) -> u64 {
1798
0
        self.initial_address
1799
0
    }
1800
1801
    /// One more than the last address that this entry has unwind information for.
1802
    ///
1803
    /// This uses wrapping arithmetic, so the result may be less than
1804
    /// `initial_address`.
1805
0
    pub fn end_address(&self) -> u64 {
1806
0
        self.initial_address
1807
0
            .wrapping_add_sized(self.address_range, self.cie.address_size)
1808
0
    }
1809
1810
    /// The number of bytes of instructions that this entry has unwind
1811
    /// information for.
1812
0
    pub fn len(&self) -> u64 {
1813
0
        self.address_range
1814
0
    }
1815
1816
    /// Return `true` if the given address is within this FDE, `false`
1817
    /// otherwise.
1818
    ///
1819
    /// This is equivalent to `entry.initial_address() <= address <
1820
    /// entry.initial_address() + entry.len()`.
1821
0
    pub fn contains(&self, address: u64) -> bool {
1822
0
        self.initial_address() <= address && address < self.end_address()
1823
0
    }
1824
1825
    /// The address of this FDE's language-specific data area (LSDA), if it has
1826
    /// any.
1827
0
    pub fn lsda(&self) -> Option<Pointer> {
1828
0
        self.augmentation.as_ref().and_then(|a| a.lsda)
1829
0
    }
1830
1831
    /// Return true if this FDE's function is a trampoline for a signal handler.
1832
    #[inline]
1833
0
    pub fn is_signal_trampoline(&self) -> bool {
1834
0
        self.cie().is_signal_trampoline()
1835
0
    }
1836
1837
    /// Return the address of the FDE's function's personality routine
1838
    /// handler. The personality routine does language-specific clean up when
1839
    /// unwinding the stack frames with the intent to not run them again.
1840
    #[inline]
1841
0
    pub fn personality(&self) -> Option<Pointer> {
1842
0
        self.cie().personality()
1843
0
    }
1844
}
1845
1846
/// Specification of what storage should be used for [`UnwindContext`].
1847
///
1848
#[cfg_attr(
1849
    feature = "read",
1850
    doc = "
1851
Normally you would only need to use [`StoreOnHeap`], which places the stack
1852
on the heap using [`Box`]. This is the default storage type parameter for [`UnwindContext`].
1853
1854
You may want to supply your own storage type for one of the following reasons:
1855
1856
  1. In rare cases you may run into failed unwinds due to the fixed stack size
1857
     used by [`StoreOnHeap`], so you may want to try a larger `Box`. If denial
1858
     of service is not a concern, then you could also try a `Vec`-based stack which
1859
     can grow as needed.
1860
  2. You may want to avoid heap allocations entirely. You can use a fixed-size
1861
     stack with in-line arrays, which will place the entire storage in-line into
1862
     [`UnwindContext`].
1863
"
1864
)]
1865
///
1866
/// Here's an implementation which uses a fixed-size stack and allocates everything in-line,
1867
/// which will cause `UnwindContext` to be large:
1868
///
1869
/// ```rust,no_run
1870
/// # use gimli::*;
1871
/// #
1872
/// # fn foo<'a>(some_fde: gimli::FrameDescriptionEntry<gimli::EndianSlice<'a, gimli::LittleEndian>>)
1873
/// #            -> gimli::Result<()> {
1874
/// # let eh_frame: gimli::EhFrame<_> = unreachable!();
1875
/// # let bases = unimplemented!();
1876
/// #
1877
/// struct StoreOnStack;
1878
///
1879
/// impl<T: ReaderOffset> UnwindContextStorage<T> for StoreOnStack {
1880
///     type Rules = [(Register, RegisterRule<T>); 192];
1881
///     type Stack = [UnwindTableRow<T, Self>; 4];
1882
/// }
1883
///
1884
/// let mut ctx = UnwindContext::<_, StoreOnStack>::new_in();
1885
///
1886
/// // Initialize the context by evaluating the CIE's initial instruction program,
1887
/// // and generate the unwind table.
1888
/// let mut table = some_fde.rows(&eh_frame, &bases, &mut ctx)?;
1889
/// while let Some(row) = table.next_row()? {
1890
///     // Do stuff with each row...
1891
/// #   let _ = row;
1892
/// }
1893
/// # unreachable!()
1894
/// # }
1895
/// ```
1896
pub trait UnwindContextStorage<T: ReaderOffset>: Sized {
1897
    /// The storage used for register rules in a unwind table row.
1898
    ///
1899
    /// Note that this is nested within the stack.
1900
    type Rules: ArrayLike<Item = (Register, RegisterRule<T>)>;
1901
1902
    /// The storage used for unwind table row stack.
1903
    type Stack: ArrayLike<Item = UnwindTableRow<T, Self>>;
1904
}
1905
1906
#[cfg(feature = "read")]
1907
const MAX_RULES: usize = 192;
1908
#[cfg(feature = "read")]
1909
const MAX_UNWIND_STACK_DEPTH: usize = 4;
1910
1911
#[cfg(feature = "read")]
1912
impl<T: ReaderOffset> UnwindContextStorage<T> for StoreOnHeap {
1913
    type Rules = [(Register, RegisterRule<T>); MAX_RULES];
1914
    type Stack = Box<[UnwindTableRow<T, Self>; MAX_UNWIND_STACK_DEPTH]>;
1915
}
1916
1917
/// Common context needed when evaluating the call frame unwinding information.
1918
///
1919
/// By default, this structure is small and allocates its internal storage
1920
/// on the heap using [`Box`] during [`UnwindContext::new`].
1921
///
1922
/// This can be overridden by providing a custom [`UnwindContextStorage`] type parameter.
1923
/// When using a custom storage with in-line arrays, the [`UnwindContext`] type itself
1924
/// will be big, so in that case it's recommended to place [`UnwindContext`] on the
1925
/// heap, e.g. using `Box::new(UnwindContext::<R, MyCustomStorage>::new_in())`.
1926
///
1927
/// To avoid re-allocating the context multiple times when evaluating multiple
1928
/// CFI programs, the same [`UnwindContext`] can be reused for multiple unwinds.
1929
///
1930
/// ```
1931
/// use gimli::{UnwindContext, UnwindTable};
1932
///
1933
/// # fn foo<'a>(some_fde: gimli::FrameDescriptionEntry<gimli::EndianSlice<'a, gimli::LittleEndian>>)
1934
/// #            -> gimli::Result<()> {
1935
/// # let eh_frame: gimli::EhFrame<_> = unreachable!();
1936
/// # let bases = unimplemented!();
1937
/// // An uninitialized context.
1938
/// let mut ctx = UnwindContext::new();
1939
///
1940
/// // Initialize the context by evaluating the CIE's initial instruction program,
1941
/// // and generate the unwind table.
1942
/// let mut table = some_fde.rows(&eh_frame, &bases, &mut ctx)?;
1943
/// while let Some(row) = table.next_row()? {
1944
///     // Do stuff with each row...
1945
/// #   let _ = row;
1946
/// }
1947
/// # unreachable!()
1948
/// # }
1949
/// ```
1950
#[derive(Clone, PartialEq, Eq)]
1951
pub struct UnwindContext<T, S = StoreOnHeap>
1952
where
1953
    T: ReaderOffset,
1954
    S: UnwindContextStorage<T>,
1955
{
1956
    // Stack of rows. The last row is the row currently being built by the
1957
    // program. There is always at least one row. The vast majority of CFI
1958
    // programs will only ever have one row on the stack.
1959
    stack: ArrayVec<S::Stack>,
1960
1961
    // If we are evaluating an FDE's instructions, then `is_initialized` will be
1962
    // `true`. If `initial_rule` is `Some`, then the initial register rules are either
1963
    // all default rules or have just 1 non-default rule, stored in `initial_rule`.
1964
    // If it's `None`, `stack[0]` will contain the initial register rules
1965
    // described by the CIE's initial instructions. These rules are used by
1966
    // `DW_CFA_restore`. Otherwise, when we are currently evaluating a CIE's
1967
    // initial instructions, `is_initialized` will be `false` and initial rules
1968
    // cannot be read.
1969
    initial_rule: Option<(Register, RegisterRule<T>)>,
1970
1971
    is_initialized: bool,
1972
}
1973
1974
impl<T, S> Debug for UnwindContext<T, S>
1975
where
1976
    T: ReaderOffset,
1977
    S: UnwindContextStorage<T>,
1978
{
1979
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1980
0
        f.debug_struct("UnwindContext")
1981
0
            .field("stack", &self.stack)
1982
0
            .field("initial_rule", &self.initial_rule)
1983
0
            .field("is_initialized", &self.is_initialized)
1984
0
            .finish()
1985
0
    }
1986
}
1987
1988
impl<T, S> Default for UnwindContext<T, S>
1989
where
1990
    T: ReaderOffset,
1991
    S: UnwindContextStorage<T>,
1992
{
1993
0
    fn default() -> Self {
1994
0
        Self::new_in()
1995
0
    }
1996
}
1997
1998
#[cfg(feature = "read")]
1999
impl<T: ReaderOffset> UnwindContext<T> {
2000
    /// Construct a new call frame unwinding context.
2001
0
    pub fn new() -> Self {
2002
0
        Self::new_in()
2003
0
    }
2004
}
2005
2006
/// # Signal Safe Methods
2007
///
2008
/// These methods are guaranteed not to allocate, acquire locks, or perform any
2009
/// other signal-unsafe operations, if an non-allocating storage is used.
2010
impl<T, S> UnwindContext<T, S>
2011
where
2012
    T: ReaderOffset,
2013
    S: UnwindContextStorage<T>,
2014
{
2015
    /// Construct a new call frame unwinding context.
2016
0
    pub fn new_in() -> Self {
2017
0
        let mut ctx = UnwindContext {
2018
0
            stack: Default::default(),
2019
0
            initial_rule: None,
2020
0
            is_initialized: false,
2021
0
        };
2022
0
        ctx.reset();
2023
0
        ctx
2024
0
    }
2025
2026
    /// Run the CIE's initial instructions and initialize this `UnwindContext`.
2027
0
    fn initialize<Section, R>(
2028
0
        &mut self,
2029
0
        section: &Section,
2030
0
        bases: &BaseAddresses,
2031
0
        cie: &CommonInformationEntry<R>,
2032
0
    ) -> Result<()>
2033
0
    where
2034
0
        R: Reader<Offset = T>,
2035
0
        Section: UnwindSection<R>,
2036
    {
2037
        // Always reset because previous initialization failure may leave dirty state.
2038
0
        self.reset();
2039
2040
0
        let mut table = UnwindTable::new_for_cie(section, bases, self, cie);
2041
0
        while table.next_row()?.is_some() {}
2042
2043
0
        self.save_initial_rules()?;
2044
0
        Ok(())
2045
0
    }
2046
2047
0
    fn reset(&mut self) {
2048
0
        self.stack.clear();
2049
0
        self.stack.try_push(UnwindTableRow::default()).unwrap();
2050
0
        debug_assert!(self.stack[0].is_default());
2051
0
        self.initial_rule = None;
2052
0
        self.is_initialized = false;
2053
0
    }
2054
2055
0
    fn row(&self) -> &UnwindTableRow<T, S> {
2056
0
        self.stack.last().unwrap()
2057
0
    }
2058
2059
0
    fn row_mut(&mut self) -> &mut UnwindTableRow<T, S> {
2060
0
        self.stack.last_mut().unwrap()
2061
0
    }
2062
2063
0
    fn save_initial_rules(&mut self) -> Result<()> {
2064
0
        debug_assert!(!self.is_initialized);
2065
0
        self.initial_rule = match *self.stack.last().unwrap().registers.rules {
2066
            // All rules are default (undefined). In this case just synthesize
2067
            // an undefined rule.
2068
0
            [] => Some((Register(0), RegisterRule::Undefined)),
2069
0
            [ref rule] => Some(rule.clone()),
2070
            _ => {
2071
0
                let rules = self.stack.last().unwrap().clone();
2072
0
                self.stack
2073
0
                    .try_insert(0, rules)
2074
0
                    .map_err(|_| Error::StackFull)?;
2075
0
                None
2076
            }
2077
        };
2078
0
        self.is_initialized = true;
2079
0
        Ok(())
2080
0
    }
2081
2082
0
    fn start_address(&self) -> u64 {
2083
0
        self.row().start_address
2084
0
    }
2085
2086
0
    fn set_start_address(&mut self, start_address: u64) {
2087
0
        let row = self.row_mut();
2088
0
        row.start_address = start_address;
2089
0
    }
2090
2091
0
    fn set_register_rule(&mut self, register: Register, rule: RegisterRule<T>) -> Result<()> {
2092
0
        let row = self.row_mut();
2093
0
        row.registers.set(register, rule)
2094
0
    }
2095
2096
    /// Returns `None` if we have not completed evaluation of a CIE's initial
2097
    /// instructions.
2098
0
    fn get_initial_rule(&self, register: Register) -> Option<RegisterRule<T>> {
2099
0
        if !self.is_initialized {
2100
0
            return None;
2101
0
        }
2102
0
        Some(match self.initial_rule {
2103
0
            None => self.stack[0].registers.get(register),
2104
0
            Some((r, ref rule)) if r == register => rule.clone(),
2105
0
            _ => RegisterRule::Undefined,
2106
        })
2107
0
    }
2108
2109
0
    fn set_cfa(&mut self, cfa: CfaRule<T>) {
2110
0
        self.row_mut().cfa = cfa;
2111
0
    }
2112
2113
0
    fn cfa_mut(&mut self) -> &mut CfaRule<T> {
2114
0
        &mut self.row_mut().cfa
2115
0
    }
2116
2117
0
    fn push_row(&mut self) -> Result<()> {
2118
0
        let new_row = self.row().clone();
2119
0
        self.stack.try_push(new_row).map_err(|_| Error::StackFull)
2120
0
    }
2121
2122
0
    fn pop_row(&mut self) -> Result<()> {
2123
0
        let min_size = if self.is_initialized && self.initial_rule.is_none() {
2124
0
            2
2125
        } else {
2126
0
            1
2127
        };
2128
0
        if self.stack.len() <= min_size {
2129
0
            return Err(Error::PopWithEmptyStack);
2130
0
        }
2131
0
        self.stack.pop().unwrap();
2132
0
        Ok(())
2133
0
    }
2134
}
2135
2136
/// The `UnwindTable` iteratively evaluates a `FrameDescriptionEntry`'s
2137
/// `CallFrameInstruction` program, yielding the each row one at a time.
2138
///
2139
/// > 6.4.1 Structure of Call Frame Information
2140
/// >
2141
/// > DWARF supports virtual unwinding by defining an architecture independent
2142
/// > basis for recording how procedures save and restore registers during their
2143
/// > lifetimes. This basis must be augmented on some machines with specific
2144
/// > information that is defined by an architecture specific ABI authoring
2145
/// > committee, a hardware vendor, or a compiler producer. The body defining a
2146
/// > specific augmentation is referred to below as the “augmenter.”
2147
/// >
2148
/// > Abstractly, this mechanism describes a very large table that has the
2149
/// > following structure:
2150
/// >
2151
/// > <table>
2152
/// >   <tr>
2153
/// >     <th>LOC</th><th>CFA</th><th>R0</th><th>R1</th><td>...</td><th>RN</th>
2154
/// >   </tr>
2155
/// >   <tr>
2156
/// >     <th>L0</th> <td></td>   <td></td>  <td></td>  <td></td>   <td></td>
2157
/// >   </tr>
2158
/// >   <tr>
2159
/// >     <th>L1</th> <td></td>   <td></td>  <td></td>  <td></td>   <td></td>
2160
/// >   </tr>
2161
/// >   <tr>
2162
/// >     <td>...</td><td></td>   <td></td>  <td></td>  <td></td>   <td></td>
2163
/// >   </tr>
2164
/// >   <tr>
2165
/// >     <th>LN</th> <td></td>   <td></td>  <td></td>  <td></td>   <td></td>
2166
/// >   </tr>
2167
/// > </table>
2168
/// >
2169
/// > The first column indicates an address for every location that contains code
2170
/// > in a program. (In shared objects, this is an object-relative offset.) The
2171
/// > remaining columns contain virtual unwinding rules that are associated with
2172
/// > the indicated location.
2173
/// >
2174
/// > The CFA column defines the rule which computes the Canonical Frame Address
2175
/// > value; it may be either a register and a signed offset that are added
2176
/// > together, or a DWARF expression that is evaluated.
2177
/// >
2178
/// > The remaining columns are labeled by register number. This includes some
2179
/// > registers that have special designation on some architectures such as the PC
2180
/// > and the stack pointer register. (The actual mapping of registers for a
2181
/// > particular architecture is defined by the augmenter.) The register columns
2182
/// > contain rules that describe whether a given register has been saved and the
2183
/// > rule to find the value for the register in the previous frame.
2184
/// >
2185
/// > ...
2186
/// >
2187
/// > This table would be extremely large if actually constructed as
2188
/// > described. Most of the entries at any point in the table are identical to
2189
/// > the ones above them. The whole table can be represented quite compactly by
2190
/// > recording just the differences starting at the beginning address of each
2191
/// > subroutine in the program.
2192
#[derive(Debug)]
2193
pub struct UnwindTable<'a, 'ctx, R, S = StoreOnHeap>
2194
where
2195
    R: Reader,
2196
    S: UnwindContextStorage<R::Offset>,
2197
{
2198
    code_alignment_factor: Wrapping<u64>,
2199
    data_alignment_factor: Wrapping<i64>,
2200
    address_size: u8,
2201
    next_start_address: u64,
2202
    last_end_address: u64,
2203
    returned_last_row: bool,
2204
    current_row_valid: bool,
2205
    instructions: CallFrameInstructionIter<'a, R>,
2206
    ctx: &'ctx mut UnwindContext<R::Offset, S>,
2207
}
2208
2209
/// # Signal Safe Methods
2210
///
2211
/// These methods are guaranteed not to allocate, acquire locks, or perform any
2212
/// other signal-unsafe operations.
2213
impl<'a, 'ctx, R, S> UnwindTable<'a, 'ctx, R, S>
2214
where
2215
    R: Reader,
2216
    S: UnwindContextStorage<R::Offset>,
2217
{
2218
    /// Construct a new `UnwindTable` for the given
2219
    /// `FrameDescriptionEntry`'s CFI unwinding program.
2220
0
    pub fn new<Section: UnwindSection<R>>(
2221
0
        section: &'a Section,
2222
0
        bases: &'a BaseAddresses,
2223
0
        ctx: &'ctx mut UnwindContext<R::Offset, S>,
2224
0
        fde: &FrameDescriptionEntry<R>,
2225
0
    ) -> Result<Self> {
2226
0
        ctx.initialize(section, bases, fde.cie())?;
2227
0
        Ok(Self::new_for_fde(section, bases, ctx, fde))
2228
0
    }
2229
2230
0
    fn new_for_fde<Section: UnwindSection<R>>(
2231
0
        section: &'a Section,
2232
0
        bases: &'a BaseAddresses,
2233
0
        ctx: &'ctx mut UnwindContext<R::Offset, S>,
2234
0
        fde: &FrameDescriptionEntry<R>,
2235
0
    ) -> Self {
2236
0
        assert!(!ctx.stack.is_empty());
2237
0
        UnwindTable {
2238
0
            code_alignment_factor: Wrapping(fde.cie().code_alignment_factor()),
2239
0
            data_alignment_factor: Wrapping(fde.cie().data_alignment_factor()),
2240
0
            address_size: fde.cie().address_size,
2241
0
            next_start_address: fde.initial_address(),
2242
0
            last_end_address: fde.end_address(),
2243
0
            returned_last_row: false,
2244
0
            current_row_valid: false,
2245
0
            instructions: fde.instructions(section, bases),
2246
0
            ctx,
2247
0
        }
2248
0
    }
2249
2250
0
    fn new_for_cie<Section: UnwindSection<R>>(
2251
0
        section: &'a Section,
2252
0
        bases: &'a BaseAddresses,
2253
0
        ctx: &'ctx mut UnwindContext<R::Offset, S>,
2254
0
        cie: &CommonInformationEntry<R>,
2255
0
    ) -> Self {
2256
0
        assert!(!ctx.stack.is_empty());
2257
0
        UnwindTable {
2258
0
            code_alignment_factor: Wrapping(cie.code_alignment_factor()),
2259
0
            data_alignment_factor: Wrapping(cie.data_alignment_factor()),
2260
0
            address_size: cie.address_size,
2261
0
            next_start_address: 0,
2262
0
            last_end_address: 0,
2263
0
            returned_last_row: false,
2264
0
            current_row_valid: false,
2265
0
            instructions: cie.instructions(section, bases),
2266
0
            ctx,
2267
0
        }
2268
0
    }
2269
2270
    /// Evaluate call frame instructions until the next row of the table is
2271
    /// completed, and return it.
2272
    ///
2273
    /// Unfortunately, this cannot be used with `FallibleIterator` because of
2274
    /// the restricted lifetime of the yielded item.
2275
0
    pub fn next_row(&mut self) -> Result<Option<&UnwindTableRow<R::Offset, S>>> {
2276
0
        assert!(!self.ctx.stack.is_empty());
2277
0
        self.ctx.set_start_address(self.next_start_address);
2278
0
        self.current_row_valid = false;
2279
2280
        loop {
2281
0
            match self.instructions.next() {
2282
0
                Err(e) => return Err(e),
2283
2284
                Ok(None) => {
2285
0
                    if self.returned_last_row {
2286
0
                        return Ok(None);
2287
0
                    }
2288
2289
0
                    let row = self.ctx.row_mut();
2290
0
                    row.end_address = self.last_end_address;
2291
2292
0
                    self.returned_last_row = true;
2293
0
                    self.current_row_valid = true;
2294
0
                    return Ok(Some(row));
2295
                }
2296
2297
0
                Ok(Some(instruction)) => {
2298
0
                    if self.evaluate(instruction)? {
2299
0
                        self.current_row_valid = true;
2300
0
                        return Ok(Some(self.ctx.row()));
2301
0
                    }
2302
                }
2303
            };
2304
        }
2305
0
    }
2306
2307
    /// Returns the current row with the lifetime of the context.
2308
0
    pub fn into_current_row(self) -> Option<&'ctx UnwindTableRow<R::Offset, S>> {
2309
0
        if self.current_row_valid {
2310
0
            Some(self.ctx.row())
2311
        } else {
2312
0
            None
2313
        }
2314
0
    }
2315
2316
    /// Evaluate one call frame instruction. Return `Ok(true)` if the row is
2317
    /// complete, `Ok(false)` otherwise.
2318
0
    fn evaluate(&mut self, instruction: CallFrameInstruction<R::Offset>) -> Result<bool> {
2319
        use crate::CallFrameInstruction::*;
2320
2321
0
        match instruction {
2322
            // Instructions that complete the current row and advance the
2323
            // address for the next row.
2324
0
            SetLoc { address } => {
2325
0
                if address < self.ctx.start_address() {
2326
0
                    return Err(Error::InvalidAddressRange);
2327
0
                }
2328
2329
0
                self.next_start_address = address;
2330
0
                self.ctx.row_mut().end_address = self.next_start_address;
2331
0
                return Ok(true);
2332
            }
2333
0
            AdvanceLoc { delta } => {
2334
0
                let delta = Wrapping(u64::from(delta)) * self.code_alignment_factor;
2335
0
                self.next_start_address = self
2336
0
                    .ctx
2337
0
                    .start_address()
2338
0
                    .add_sized(delta.0, self.address_size)?;
2339
0
                self.ctx.row_mut().end_address = self.next_start_address;
2340
0
                return Ok(true);
2341
            }
2342
2343
            // Instructions that modify the CFA.
2344
0
            DefCfa { register, offset } => {
2345
0
                self.ctx.set_cfa(CfaRule::RegisterAndOffset {
2346
0
                    register,
2347
0
                    offset: offset as i64,
2348
0
                });
2349
0
            }
2350
            DefCfaSf {
2351
0
                register,
2352
0
                factored_offset,
2353
0
            } => {
2354
0
                let data_align = self.data_alignment_factor;
2355
0
                self.ctx.set_cfa(CfaRule::RegisterAndOffset {
2356
0
                    register,
2357
0
                    offset: (Wrapping(factored_offset) * data_align).0,
2358
0
                });
2359
0
            }
2360
0
            DefCfaRegister { register } => {
2361
                if let CfaRule::RegisterAndOffset {
2362
0
                    register: ref mut reg,
2363
                    ..
2364
0
                } = *self.ctx.cfa_mut()
2365
0
                {
2366
0
                    *reg = register;
2367
0
                } else {
2368
0
                    return Err(Error::CfiInstructionInInvalidContext);
2369
                }
2370
            }
2371
0
            DefCfaOffset { offset } => {
2372
                if let CfaRule::RegisterAndOffset {
2373
0
                    offset: ref mut off,
2374
                    ..
2375
0
                } = *self.ctx.cfa_mut()
2376
0
                {
2377
0
                    *off = offset as i64;
2378
0
                } else {
2379
0
                    return Err(Error::CfiInstructionInInvalidContext);
2380
                }
2381
            }
2382
0
            DefCfaOffsetSf { factored_offset } => {
2383
                if let CfaRule::RegisterAndOffset {
2384
0
                    offset: ref mut off,
2385
                    ..
2386
0
                } = *self.ctx.cfa_mut()
2387
0
                {
2388
0
                    let data_align = self.data_alignment_factor;
2389
0
                    *off = (Wrapping(factored_offset) * data_align).0;
2390
0
                } else {
2391
0
                    return Err(Error::CfiInstructionInInvalidContext);
2392
                }
2393
            }
2394
0
            DefCfaExpression { expression } => {
2395
0
                self.ctx.set_cfa(CfaRule::Expression(expression));
2396
0
            }
2397
2398
            // Instructions that define register rules.
2399
0
            Undefined { register } => {
2400
0
                self.ctx
2401
0
                    .set_register_rule(register, RegisterRule::Undefined)?;
2402
            }
2403
0
            SameValue { register } => {
2404
0
                self.ctx
2405
0
                    .set_register_rule(register, RegisterRule::SameValue)?;
2406
            }
2407
            Offset {
2408
0
                register,
2409
0
                factored_offset,
2410
            } => {
2411
0
                let offset = Wrapping(factored_offset as i64) * self.data_alignment_factor;
2412
0
                self.ctx
2413
0
                    .set_register_rule(register, RegisterRule::Offset(offset.0))?;
2414
            }
2415
            OffsetExtendedSf {
2416
0
                register,
2417
0
                factored_offset,
2418
            } => {
2419
0
                let offset = Wrapping(factored_offset) * self.data_alignment_factor;
2420
0
                self.ctx
2421
0
                    .set_register_rule(register, RegisterRule::Offset(offset.0))?;
2422
            }
2423
            ValOffset {
2424
0
                register,
2425
0
                factored_offset,
2426
            } => {
2427
0
                let offset = Wrapping(factored_offset as i64) * self.data_alignment_factor;
2428
0
                self.ctx
2429
0
                    .set_register_rule(register, RegisterRule::ValOffset(offset.0))?;
2430
            }
2431
            ValOffsetSf {
2432
0
                register,
2433
0
                factored_offset,
2434
            } => {
2435
0
                let offset = Wrapping(factored_offset) * self.data_alignment_factor;
2436
0
                self.ctx
2437
0
                    .set_register_rule(register, RegisterRule::ValOffset(offset.0))?;
2438
            }
2439
            Register {
2440
0
                dest_register,
2441
0
                src_register,
2442
            } => {
2443
0
                self.ctx
2444
0
                    .set_register_rule(dest_register, RegisterRule::Register(src_register))?;
2445
            }
2446
            Expression {
2447
0
                register,
2448
0
                expression,
2449
            } => {
2450
0
                let expression = RegisterRule::Expression(expression);
2451
0
                self.ctx.set_register_rule(register, expression)?;
2452
            }
2453
            ValExpression {
2454
0
                register,
2455
0
                expression,
2456
            } => {
2457
0
                let expression = RegisterRule::ValExpression(expression);
2458
0
                self.ctx.set_register_rule(register, expression)?;
2459
            }
2460
0
            Restore { register } => {
2461
0
                let initial_rule = if let Some(rule) = self.ctx.get_initial_rule(register) {
2462
0
                    rule
2463
                } else {
2464
                    // Can't restore the initial rule when we are
2465
                    // evaluating the initial rules!
2466
0
                    return Err(Error::CfiInstructionInInvalidContext);
2467
                };
2468
2469
0
                self.ctx.set_register_rule(register, initial_rule)?;
2470
            }
2471
2472
            // Row push and pop instructions.
2473
            RememberState => {
2474
0
                self.ctx.push_row()?;
2475
            }
2476
            RestoreState => {
2477
                // Pop state while preserving current location.
2478
0
                let start_address = self.ctx.start_address();
2479
0
                self.ctx.pop_row()?;
2480
0
                self.ctx.set_start_address(start_address);
2481
            }
2482
2483
            // GNU Extension. Save the size somewhere so the unwinder can use
2484
            // it when restoring IP
2485
0
            ArgsSize { size } => {
2486
0
                self.ctx.row_mut().saved_args_size = size;
2487
0
            }
2488
2489
            // AArch64 extension.
2490
            NegateRaState => {
2491
0
                let register = crate::AArch64::RA_SIGN_STATE;
2492
0
                let value = match self.ctx.row().register(register) {
2493
0
                    RegisterRule::Undefined => 0,
2494
0
                    RegisterRule::Constant(value) => value,
2495
0
                    _ => return Err(Error::CfiInstructionInInvalidContext),
2496
                };
2497
0
                self.ctx
2498
0
                    .set_register_rule(register, RegisterRule::Constant(value ^ 1))?;
2499
            }
2500
2501
            // No operation.
2502
0
            Nop => {}
2503
        };
2504
2505
0
        Ok(false)
2506
0
    }
2507
}
2508
2509
// We tend to have very few register rules: usually only a couple. Even if we
2510
// have a rule for every register, on x86-64 with SSE and everything we're
2511
// talking about ~100 rules. So rather than keeping the rules in a hash map, or
2512
// a vector indexed by register number (which would lead to filling lots of
2513
// empty entries), we store them as a vec of (register number, register rule)
2514
// pairs.
2515
//
2516
// Additionally, because every register's default rule is implicitly
2517
// `RegisterRule::Undefined`, we never store a register's rule in this vec if it
2518
// is undefined and save a little bit more space and do a little fewer
2519
// comparisons that way.
2520
//
2521
// The maximum number of rules preallocated by libunwind is 97 for AArch64, 128
2522
// for ARM, and even 188 for MIPS. It is extremely unlikely to encounter this
2523
// many register rules in practice.
2524
//
2525
// See:
2526
// - https://github.com/libunwind/libunwind/blob/11fd461095ea98f4b3e3a361f5a8a558519363fa/include/tdep-x86_64/dwarf-config.h#L36
2527
// - https://github.com/libunwind/libunwind/blob/11fd461095ea98f4b3e3a361f5a8a558519363fa/include/tdep-aarch64/dwarf-config.h#L32
2528
// - https://github.com/libunwind/libunwind/blob/11fd461095ea98f4b3e3a361f5a8a558519363fa/include/tdep-arm/dwarf-config.h#L31
2529
// - https://github.com/libunwind/libunwind/blob/11fd461095ea98f4b3e3a361f5a8a558519363fa/include/tdep-mips/dwarf-config.h#L31
2530
struct RegisterRuleMap<T, S = StoreOnHeap>
2531
where
2532
    T: ReaderOffset,
2533
    S: UnwindContextStorage<T>,
2534
{
2535
    rules: ArrayVec<S::Rules>,
2536
}
2537
2538
impl<T, S> Debug for RegisterRuleMap<T, S>
2539
where
2540
    T: ReaderOffset,
2541
    S: UnwindContextStorage<T>,
2542
{
2543
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2544
0
        f.debug_struct("RegisterRuleMap")
2545
0
            .field("rules", &self.rules)
2546
0
            .finish()
2547
0
    }
2548
}
2549
2550
impl<T, S> Clone for RegisterRuleMap<T, S>
2551
where
2552
    T: ReaderOffset,
2553
    S: UnwindContextStorage<T>,
2554
{
2555
0
    fn clone(&self) -> Self {
2556
0
        Self {
2557
0
            rules: self.rules.clone(),
2558
0
        }
2559
0
    }
2560
}
2561
2562
impl<T, S> Default for RegisterRuleMap<T, S>
2563
where
2564
    T: ReaderOffset,
2565
    S: UnwindContextStorage<T>,
2566
{
2567
0
    fn default() -> Self {
2568
0
        RegisterRuleMap {
2569
0
            rules: Default::default(),
2570
0
        }
2571
0
    }
2572
}
2573
2574
/// # Signal Safe Methods
2575
///
2576
/// These methods are guaranteed not to allocate, acquire locks, or perform any
2577
/// other signal-unsafe operations.
2578
impl<T, S> RegisterRuleMap<T, S>
2579
where
2580
    T: ReaderOffset,
2581
    S: UnwindContextStorage<T>,
2582
{
2583
0
    fn is_default(&self) -> bool {
2584
0
        self.rules.is_empty()
2585
0
    }
2586
2587
0
    fn get(&self, register: Register) -> RegisterRule<T> {
2588
0
        self.rules
2589
0
            .iter()
2590
0
            .find(|rule| rule.0 == register)
2591
0
            .map(|r| {
2592
0
                debug_assert!(r.1.is_defined());
2593
0
                r.1.clone()
2594
0
            })
2595
0
            .unwrap_or(RegisterRule::Undefined)
2596
0
    }
2597
2598
0
    fn set(&mut self, register: Register, rule: RegisterRule<T>) -> Result<()> {
2599
0
        if !rule.is_defined() {
2600
0
            let idx = self
2601
0
                .rules
2602
0
                .iter()
2603
0
                .enumerate()
2604
0
                .find(|&(_, r)| r.0 == register)
2605
0
                .map(|(i, _)| i);
2606
0
            if let Some(idx) = idx {
2607
0
                self.rules.swap_remove(idx);
2608
0
            }
2609
0
            return Ok(());
2610
0
        }
2611
2612
0
        for &mut (reg, ref mut old_rule) in &mut *self.rules {
2613
0
            debug_assert!(old_rule.is_defined());
2614
0
            if reg == register {
2615
0
                *old_rule = rule;
2616
0
                return Ok(());
2617
0
            }
2618
        }
2619
2620
0
        self.rules
2621
0
            .try_push((register, rule))
2622
0
            .map_err(|_| Error::TooManyRegisterRules)
2623
0
    }
2624
2625
0
    fn iter(&self) -> RegisterRuleIter<'_, T> {
2626
0
        RegisterRuleIter(self.rules.iter())
2627
0
    }
2628
}
2629
2630
impl<'a, R, S> FromIterator<&'a (Register, RegisterRule<R>)> for RegisterRuleMap<R, S>
2631
where
2632
    R: 'a + ReaderOffset,
2633
    S: UnwindContextStorage<R>,
2634
{
2635
0
    fn from_iter<T>(iter: T) -> Self
2636
0
    where
2637
0
        T: IntoIterator<Item = &'a (Register, RegisterRule<R>)>,
2638
    {
2639
0
        let iter = iter.into_iter();
2640
0
        let mut rules = RegisterRuleMap::default();
2641
0
        for &(reg, ref rule) in iter.filter(|r| r.1.is_defined()) {
2642
0
            rules.set(reg, rule.clone()).expect(
2643
0
                "This is only used in tests, impl isn't exposed publicly.
2644
0
                         If you trip this, fix your test",
2645
0
            );
2646
0
        }
2647
0
        rules
2648
0
    }
2649
}
2650
2651
impl<T, S> PartialEq for RegisterRuleMap<T, S>
2652
where
2653
    T: ReaderOffset + PartialEq,
2654
    S: UnwindContextStorage<T>,
2655
{
2656
0
    fn eq(&self, rhs: &Self) -> bool {
2657
0
        for &(reg, ref rule) in &*self.rules {
2658
0
            debug_assert!(rule.is_defined());
2659
0
            if *rule != rhs.get(reg) {
2660
0
                return false;
2661
0
            }
2662
        }
2663
2664
0
        for &(reg, ref rhs_rule) in &*rhs.rules {
2665
0
            debug_assert!(rhs_rule.is_defined());
2666
0
            if *rhs_rule != self.get(reg) {
2667
0
                return false;
2668
0
            }
2669
        }
2670
2671
0
        true
2672
0
    }
2673
}
2674
2675
impl<T, S> Eq for RegisterRuleMap<T, S>
2676
where
2677
    T: ReaderOffset + Eq,
2678
    S: UnwindContextStorage<T>,
2679
{
2680
}
2681
2682
/// An unordered iterator for register rules.
2683
#[derive(Debug, Clone)]
2684
pub struct RegisterRuleIter<'iter, T>(::core::slice::Iter<'iter, (Register, RegisterRule<T>)>)
2685
where
2686
    T: ReaderOffset;
2687
2688
impl<'iter, T: ReaderOffset> Iterator for RegisterRuleIter<'iter, T> {
2689
    type Item = &'iter (Register, RegisterRule<T>);
2690
2691
0
    fn next(&mut self) -> Option<Self::Item> {
2692
0
        self.0.next()
2693
0
    }
2694
}
2695
2696
/// A row in the virtual unwind table that describes how to find the values of
2697
/// the registers in the *previous* frame for a range of PC addresses.
2698
#[derive(PartialEq, Eq)]
2699
pub struct UnwindTableRow<T, S = StoreOnHeap>
2700
where
2701
    T: ReaderOffset,
2702
    S: UnwindContextStorage<T>,
2703
{
2704
    start_address: u64,
2705
    end_address: u64,
2706
    saved_args_size: u64,
2707
    cfa: CfaRule<T>,
2708
    registers: RegisterRuleMap<T, S>,
2709
}
2710
2711
impl<T, S> Debug for UnwindTableRow<T, S>
2712
where
2713
    T: ReaderOffset,
2714
    S: UnwindContextStorage<T>,
2715
{
2716
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2717
0
        f.debug_struct("UnwindTableRow")
2718
0
            .field("start_address", &self.start_address)
2719
0
            .field("end_address", &self.end_address)
2720
0
            .field("saved_args_size", &self.saved_args_size)
2721
0
            .field("cfa", &self.cfa)
2722
0
            .field("registers", &self.registers)
2723
0
            .finish()
2724
0
    }
2725
}
2726
2727
impl<T, S> Clone for UnwindTableRow<T, S>
2728
where
2729
    T: ReaderOffset,
2730
    S: UnwindContextStorage<T>,
2731
{
2732
0
    fn clone(&self) -> Self {
2733
0
        Self {
2734
0
            start_address: self.start_address,
2735
0
            end_address: self.end_address,
2736
0
            saved_args_size: self.saved_args_size,
2737
0
            cfa: self.cfa.clone(),
2738
0
            registers: self.registers.clone(),
2739
0
        }
2740
0
    }
2741
}
2742
2743
impl<T, S> Default for UnwindTableRow<T, S>
2744
where
2745
    T: ReaderOffset,
2746
    S: UnwindContextStorage<T>,
2747
{
2748
0
    fn default() -> Self {
2749
0
        UnwindTableRow {
2750
0
            start_address: 0,
2751
0
            end_address: 0,
2752
0
            saved_args_size: 0,
2753
0
            cfa: Default::default(),
2754
0
            registers: Default::default(),
2755
0
        }
2756
0
    }
2757
}
2758
2759
impl<T, S> UnwindTableRow<T, S>
2760
where
2761
    T: ReaderOffset,
2762
    S: UnwindContextStorage<T>,
2763
{
2764
0
    fn is_default(&self) -> bool {
2765
0
        self.start_address == 0
2766
0
            && self.end_address == 0
2767
0
            && self.cfa.is_default()
2768
0
            && self.registers.is_default()
2769
0
    }
2770
2771
    /// Get the starting PC address that this row applies to.
2772
0
    pub fn start_address(&self) -> u64 {
2773
0
        self.start_address
2774
0
    }
2775
2776
    /// Get the end PC address where this row's register rules become
2777
    /// unapplicable.
2778
    ///
2779
    /// In other words, this row describes how to recover the last frame's
2780
    /// registers for all PCs where `row.start_address() <= PC <
2781
    /// row.end_address()`. This row does NOT describe how to recover registers
2782
    /// when `PC == row.end_address()`.
2783
0
    pub fn end_address(&self) -> u64 {
2784
0
        self.end_address
2785
0
    }
2786
2787
    /// Return `true` if the given `address` is within this row's address range,
2788
    /// `false` otherwise.
2789
0
    pub fn contains(&self, address: u64) -> bool {
2790
0
        self.start_address <= address && address < self.end_address
2791
0
    }
2792
2793
    /// Returns the amount of args currently on the stack.
2794
    ///
2795
    /// When unwinding, if the personality function requested a change in IP,
2796
    /// the SP needs to be adjusted by saved_args_size.
2797
0
    pub fn saved_args_size(&self) -> u64 {
2798
0
        self.saved_args_size
2799
0
    }
2800
2801
    /// Get the canonical frame address (CFA) recovery rule for this row.
2802
0
    pub fn cfa(&self) -> &CfaRule<T> {
2803
0
        &self.cfa
2804
0
    }
2805
2806
    /// Get the register recovery rule for the given register number.
2807
    ///
2808
    /// The register number mapping is architecture dependent. For example, in
2809
    /// the x86-64 ABI the register number mapping is defined in Figure 3.36:
2810
    ///
2811
    /// > Figure 3.36: DWARF Register Number Mapping
2812
    /// >
2813
    /// > <table>
2814
    /// >   <tr><th>Register Name</th>                    <th>Number</th>  <th>Abbreviation</th></tr>
2815
    /// >   <tr><td>General Purpose Register RAX</td>     <td>0</td>       <td>%rax</td></tr>
2816
    /// >   <tr><td>General Purpose Register RDX</td>     <td>1</td>       <td>%rdx</td></tr>
2817
    /// >   <tr><td>General Purpose Register RCX</td>     <td>2</td>       <td>%rcx</td></tr>
2818
    /// >   <tr><td>General Purpose Register RBX</td>     <td>3</td>       <td>%rbx</td></tr>
2819
    /// >   <tr><td>General Purpose Register RSI</td>     <td>4</td>       <td>%rsi</td></tr>
2820
    /// >   <tr><td>General Purpose Register RDI</td>     <td>5</td>       <td>%rdi</td></tr>
2821
    /// >   <tr><td>General Purpose Register RBP</td>     <td>6</td>       <td>%rbp</td></tr>
2822
    /// >   <tr><td>Stack Pointer Register RSP</td>       <td>7</td>       <td>%rsp</td></tr>
2823
    /// >   <tr><td>Extended Integer Registers 8-15</td>  <td>8-15</td>    <td>%r8-%r15</td></tr>
2824
    /// >   <tr><td>Return Address RA</td>                <td>16</td>      <td></td></tr>
2825
    /// >   <tr><td>Vector Registers 0–7</td>             <td>17-24</td>   <td>%xmm0–%xmm7</td></tr>
2826
    /// >   <tr><td>Extended Vector Registers 8–15</td>   <td>25-32</td>   <td>%xmm8–%xmm15</td></tr>
2827
    /// >   <tr><td>Floating Point Registers 0–7</td>     <td>33-40</td>   <td>%st0–%st7</td></tr>
2828
    /// >   <tr><td>MMX Registers 0–7</td>                <td>41-48</td>   <td>%mm0–%mm7</td></tr>
2829
    /// >   <tr><td>Flag Register</td>                    <td>49</td>      <td>%rFLAGS</td></tr>
2830
    /// >   <tr><td>Segment Register ES</td>              <td>50</td>      <td>%es</td></tr>
2831
    /// >   <tr><td>Segment Register CS</td>              <td>51</td>      <td>%cs</td></tr>
2832
    /// >   <tr><td>Segment Register SS</td>              <td>52</td>      <td>%ss</td></tr>
2833
    /// >   <tr><td>Segment Register DS</td>              <td>53</td>      <td>%ds</td></tr>
2834
    /// >   <tr><td>Segment Register FS</td>              <td>54</td>      <td>%fs</td></tr>
2835
    /// >   <tr><td>Segment Register GS</td>              <td>55</td>      <td>%gs</td></tr>
2836
    /// >   <tr><td>Reserved</td>                         <td>56-57</td>   <td></td></tr>
2837
    /// >   <tr><td>FS Base address</td>                  <td>58</td>      <td>%fs.base</td></tr>
2838
    /// >   <tr><td>GS Base address</td>                  <td>59</td>      <td>%gs.base</td></tr>
2839
    /// >   <tr><td>Reserved</td>                         <td>60-61</td>   <td></td></tr>
2840
    /// >   <tr><td>Task Register</td>                    <td>62</td>      <td>%tr</td></tr>
2841
    /// >   <tr><td>LDT Register</td>                     <td>63</td>      <td>%ldtr</td></tr>
2842
    /// >   <tr><td>128-bit Media Control and Status</td> <td>64</td>      <td>%mxcsr</td></tr>
2843
    /// >   <tr><td>x87 Control Word</td>                 <td>65</td>      <td>%fcw</td></tr>
2844
    /// >   <tr><td>x87 Status Word</td>                  <td>66</td>      <td>%fsw</td></tr>
2845
    /// >   <tr><td>Upper Vector Registers 16–31</td>     <td>67-82</td>   <td>%xmm16–%xmm31</td></tr>
2846
    /// >   <tr><td>Reserved</td>                         <td>83-117</td>  <td></td></tr>
2847
    /// >   <tr><td>Vector Mask Registers 0–7</td>        <td>118-125</td> <td>%k0–%k7</td></tr>
2848
    /// >   <tr><td>Reserved</td>                         <td>126-129</td> <td></td></tr>
2849
    /// > </table>
2850
0
    pub fn register(&self, register: Register) -> RegisterRule<T> {
2851
0
        self.registers.get(register)
2852
0
    }
2853
2854
    /// Iterate over all defined register `(number, rule)` pairs.
2855
    ///
2856
    /// The rules are not iterated in any guaranteed order. Any register that
2857
    /// does not make an appearance in the iterator implicitly has the rule
2858
    /// `RegisterRule::Undefined`.
2859
    ///
2860
    /// ```
2861
    /// # use gimli::{EndianSlice, LittleEndian, UnwindTableRow};
2862
    /// # fn foo<'input>(unwind_table_row: UnwindTableRow<usize>) {
2863
    /// for &(register, ref rule) in unwind_table_row.registers() {
2864
    ///     // ...
2865
    ///     # drop(register); drop(rule);
2866
    /// }
2867
    /// # }
2868
    /// ```
2869
0
    pub fn registers(&self) -> RegisterRuleIter<'_, T> {
2870
0
        self.registers.iter()
2871
0
    }
2872
}
2873
2874
/// The canonical frame address (CFA) recovery rules.
2875
#[derive(Clone, Debug, PartialEq, Eq)]
2876
pub enum CfaRule<T: ReaderOffset> {
2877
    /// The CFA is given offset from the given register's value.
2878
    RegisterAndOffset {
2879
        /// The register containing the base value.
2880
        register: Register,
2881
        /// The offset from the register's base value.
2882
        offset: i64,
2883
    },
2884
    /// The CFA is obtained by evaluating a DWARF expression program.
2885
    Expression(UnwindExpression<T>),
2886
}
2887
2888
impl<T: ReaderOffset> Default for CfaRule<T> {
2889
0
    fn default() -> Self {
2890
0
        CfaRule::RegisterAndOffset {
2891
0
            register: Register(0),
2892
0
            offset: 0,
2893
0
        }
2894
0
    }
2895
}
2896
2897
impl<T: ReaderOffset> CfaRule<T> {
2898
0
    fn is_default(&self) -> bool {
2899
0
        match *self {
2900
0
            CfaRule::RegisterAndOffset { register, offset } => {
2901
0
                register == Register(0) && offset == 0
2902
            }
2903
0
            _ => false,
2904
        }
2905
0
    }
2906
}
2907
2908
/// An entry in the abstract CFI table that describes how to find the value of a
2909
/// register.
2910
///
2911
/// "The register columns contain rules that describe whether a given register
2912
/// has been saved and the rule to find the value for the register in the
2913
/// previous frame."
2914
#[derive(Clone, Debug, PartialEq, Eq)]
2915
#[non_exhaustive]
2916
pub enum RegisterRule<T: ReaderOffset> {
2917
    /// > A register that has this rule has no recoverable value in the previous
2918
    /// > frame. (By convention, it is not preserved by a callee.)
2919
    Undefined,
2920
2921
    /// > This register has not been modified from the previous frame. (By
2922
    /// > convention, it is preserved by the callee, but the callee has not
2923
    /// > modified it.)
2924
    SameValue,
2925
2926
    /// "The previous value of this register is saved at the address CFA+N where
2927
    /// CFA is the current CFA value and N is a signed offset."
2928
    Offset(i64),
2929
2930
    /// "The previous value of this register is the value CFA+N where CFA is the
2931
    /// current CFA value and N is a signed offset."
2932
    ValOffset(i64),
2933
2934
    /// "The previous value of this register is stored in another register
2935
    /// numbered R."
2936
    Register(Register),
2937
2938
    /// "The previous value of this register is located at the address produced
2939
    /// by executing the DWARF expression."
2940
    Expression(UnwindExpression<T>),
2941
2942
    /// "The previous value of this register is the value produced by executing
2943
    /// the DWARF expression."
2944
    ValExpression(UnwindExpression<T>),
2945
2946
    /// "The rule is defined externally to this specification by the augmenter."
2947
    Architectural,
2948
2949
    /// This is a pseudo-register with a constant value.
2950
    Constant(u64),
2951
}
2952
2953
impl<T: ReaderOffset> RegisterRule<T> {
2954
0
    fn is_defined(&self) -> bool {
2955
0
        !matches!(*self, RegisterRule::Undefined)
2956
0
    }
2957
}
2958
2959
/// A parsed call frame instruction.
2960
#[derive(Clone, Debug, PartialEq, Eq)]
2961
pub enum CallFrameInstruction<T: ReaderOffset> {
2962
    // 6.4.2.1 Row Creation Methods
2963
    /// > 1. DW_CFA_set_loc
2964
    /// >
2965
    /// > The DW_CFA_set_loc instruction takes a single operand that represents
2966
    /// > a target address. The required action is to create a new table row
2967
    /// > using the specified address as the location. All other values in the
2968
    /// > new row are initially identical to the current row. The new location
2969
    /// > value is always greater than the current one. If the segment_size
2970
    /// > field of this FDE's CIE is non- zero, the initial location is preceded
2971
    /// > by a segment selector of the given length.
2972
    SetLoc {
2973
        /// The target address.
2974
        address: u64,
2975
    },
2976
2977
    /// The `AdvanceLoc` instruction is used for all of `DW_CFA_advance_loc` and
2978
    /// `DW_CFA_advance_loc{1,2,4}`.
2979
    ///
2980
    /// > 2. DW_CFA_advance_loc
2981
    /// >
2982
    /// > The DW_CFA_advance instruction takes a single operand (encoded with
2983
    /// > the opcode) that represents a constant delta. The required action is
2984
    /// > to create a new table row with a location value that is computed by
2985
    /// > taking the current entry’s location value and adding the value of
2986
    /// > delta * code_alignment_factor. All other values in the new row are
2987
    /// > initially identical to the current row.
2988
    AdvanceLoc {
2989
        /// The delta to be added to the current address.
2990
        delta: u32,
2991
    },
2992
2993
    // 6.4.2.2 CFA Definition Methods
2994
    /// > 1. DW_CFA_def_cfa
2995
    /// >
2996
    /// > The DW_CFA_def_cfa instruction takes two unsigned LEB128 operands
2997
    /// > representing a register number and a (non-factored) offset. The
2998
    /// > required action is to define the current CFA rule to use the provided
2999
    /// > register and offset.
3000
    DefCfa {
3001
        /// The target register's number.
3002
        register: Register,
3003
        /// The non-factored offset.
3004
        offset: u64,
3005
    },
3006
3007
    /// > 2. DW_CFA_def_cfa_sf
3008
    /// >
3009
    /// > The DW_CFA_def_cfa_sf instruction takes two operands: an unsigned
3010
    /// > LEB128 value representing a register number and a signed LEB128
3011
    /// > factored offset. This instruction is identical to DW_CFA_def_cfa
3012
    /// > except that the second operand is signed and factored. The resulting
3013
    /// > offset is factored_offset * data_alignment_factor.
3014
    DefCfaSf {
3015
        /// The target register's number.
3016
        register: Register,
3017
        /// The factored offset.
3018
        factored_offset: i64,
3019
    },
3020
3021
    /// > 3. DW_CFA_def_cfa_register
3022
    /// >
3023
    /// > The DW_CFA_def_cfa_register instruction takes a single unsigned LEB128
3024
    /// > operand representing a register number. The required action is to
3025
    /// > define the current CFA rule to use the provided register (but to keep
3026
    /// > the old offset). This operation is valid only if the current CFA rule
3027
    /// > is defined to use a register and offset.
3028
    DefCfaRegister {
3029
        /// The target register's number.
3030
        register: Register,
3031
    },
3032
3033
    /// > 4. DW_CFA_def_cfa_offset
3034
    /// >
3035
    /// > The DW_CFA_def_cfa_offset instruction takes a single unsigned LEB128
3036
    /// > operand representing a (non-factored) offset. The required action is
3037
    /// > to define the current CFA rule to use the provided offset (but to keep
3038
    /// > the old register). This operation is valid only if the current CFA
3039
    /// > rule is defined to use a register and offset.
3040
    DefCfaOffset {
3041
        /// The non-factored offset.
3042
        offset: u64,
3043
    },
3044
3045
    /// > 5. DW_CFA_def_cfa_offset_sf
3046
    /// >
3047
    /// > The DW_CFA_def_cfa_offset_sf instruction takes a signed LEB128 operand
3048
    /// > representing a factored offset. This instruction is identical to
3049
    /// > DW_CFA_def_cfa_offset except that the operand is signed and
3050
    /// > factored. The resulting offset is factored_offset *
3051
    /// > data_alignment_factor. This operation is valid only if the current CFA
3052
    /// > rule is defined to use a register and offset.
3053
    DefCfaOffsetSf {
3054
        /// The factored offset.
3055
        factored_offset: i64,
3056
    },
3057
3058
    /// > 6. DW_CFA_def_cfa_expression
3059
    /// >
3060
    /// > The DW_CFA_def_cfa_expression instruction takes a single operand
3061
    /// > encoded as a DW_FORM_exprloc value representing a DWARF
3062
    /// > expression. The required action is to establish that expression as the
3063
    /// > means by which the current CFA is computed.
3064
    DefCfaExpression {
3065
        /// The location of the DWARF expression.
3066
        expression: UnwindExpression<T>,
3067
    },
3068
3069
    // 6.4.2.3 Register Rule Instructions
3070
    /// > 1. DW_CFA_undefined
3071
    /// >
3072
    /// > The DW_CFA_undefined instruction takes a single unsigned LEB128
3073
    /// > operand that represents a register number. The required action is to
3074
    /// > set the rule for the specified register to “undefined.”
3075
    Undefined {
3076
        /// The target register's number.
3077
        register: Register,
3078
    },
3079
3080
    /// > 2. DW_CFA_same_value
3081
    /// >
3082
    /// > The DW_CFA_same_value instruction takes a single unsigned LEB128
3083
    /// > operand that represents a register number. The required action is to
3084
    /// > set the rule for the specified register to “same value.”
3085
    SameValue {
3086
        /// The target register's number.
3087
        register: Register,
3088
    },
3089
3090
    /// The `Offset` instruction represents both `DW_CFA_offset` and
3091
    /// `DW_CFA_offset_extended`.
3092
    ///
3093
    /// > 3. DW_CFA_offset
3094
    /// >
3095
    /// > The DW_CFA_offset instruction takes two operands: a register number
3096
    /// > (encoded with the opcode) and an unsigned LEB128 constant representing
3097
    /// > a factored offset. The required action is to change the rule for the
3098
    /// > register indicated by the register number to be an offset(N) rule
3099
    /// > where the value of N is factored offset * data_alignment_factor.
3100
    Offset {
3101
        /// The target register's number.
3102
        register: Register,
3103
        /// The factored offset.
3104
        factored_offset: u64,
3105
    },
3106
3107
    /// > 5. DW_CFA_offset_extended_sf
3108
    /// >
3109
    /// > The DW_CFA_offset_extended_sf instruction takes two operands: an
3110
    /// > unsigned LEB128 value representing a register number and a signed
3111
    /// > LEB128 factored offset. This instruction is identical to
3112
    /// > DW_CFA_offset_extended except that the second operand is signed and
3113
    /// > factored. The resulting offset is factored_offset *
3114
    /// > data_alignment_factor.
3115
    OffsetExtendedSf {
3116
        /// The target register's number.
3117
        register: Register,
3118
        /// The factored offset.
3119
        factored_offset: i64,
3120
    },
3121
3122
    /// > 6. DW_CFA_val_offset
3123
    /// >
3124
    /// > The DW_CFA_val_offset instruction takes two unsigned LEB128 operands
3125
    /// > representing a register number and a factored offset. The required
3126
    /// > action is to change the rule for the register indicated by the
3127
    /// > register number to be a val_offset(N) rule where the value of N is
3128
    /// > factored_offset * data_alignment_factor.
3129
    ValOffset {
3130
        /// The target register's number.
3131
        register: Register,
3132
        /// The factored offset.
3133
        factored_offset: u64,
3134
    },
3135
3136
    /// > 7. DW_CFA_val_offset_sf
3137
    /// >
3138
    /// > The DW_CFA_val_offset_sf instruction takes two operands: an unsigned
3139
    /// > LEB128 value representing a register number and a signed LEB128
3140
    /// > factored offset. This instruction is identical to DW_CFA_val_offset
3141
    /// > except that the second operand is signed and factored. The resulting
3142
    /// > offset is factored_offset * data_alignment_factor.
3143
    ValOffsetSf {
3144
        /// The target register's number.
3145
        register: Register,
3146
        /// The factored offset.
3147
        factored_offset: i64,
3148
    },
3149
3150
    /// > 8. DW_CFA_register
3151
    /// >
3152
    /// > The DW_CFA_register instruction takes two unsigned LEB128 operands
3153
    /// > representing register numbers. The required action is to set the rule
3154
    /// > for the first register to be register(R) where R is the second
3155
    /// > register.
3156
    Register {
3157
        /// The number of the register whose rule is being changed.
3158
        dest_register: Register,
3159
        /// The number of the register where the other register's value can be
3160
        /// found.
3161
        src_register: Register,
3162
    },
3163
3164
    /// > 9. DW_CFA_expression
3165
    /// >
3166
    /// > The DW_CFA_expression instruction takes two operands: an unsigned
3167
    /// > LEB128 value representing a register number, and a DW_FORM_block value
3168
    /// > representing a DWARF expression. The required action is to change the
3169
    /// > rule for the register indicated by the register number to be an
3170
    /// > expression(E) rule where E is the DWARF expression. That is, the DWARF
3171
    /// > expression computes the address. The value of the CFA is pushed on the
3172
    /// > DWARF evaluation stack prior to execution of the DWARF expression.
3173
    Expression {
3174
        /// The target register's number.
3175
        register: Register,
3176
        /// The location of the DWARF expression.
3177
        expression: UnwindExpression<T>,
3178
    },
3179
3180
    /// > 10. DW_CFA_val_expression
3181
    /// >
3182
    /// > The DW_CFA_val_expression instruction takes two operands: an unsigned
3183
    /// > LEB128 value representing a register number, and a DW_FORM_block value
3184
    /// > representing a DWARF expression. The required action is to change the
3185
    /// > rule for the register indicated by the register number to be a
3186
    /// > val_expression(E) rule where E is the DWARF expression. That is, the
3187
    /// > DWARF expression computes the value of the given register. The value
3188
    /// > of the CFA is pushed on the DWARF evaluation stack prior to execution
3189
    /// > of the DWARF expression.
3190
    ValExpression {
3191
        /// The target register's number.
3192
        register: Register,
3193
        /// The location of the DWARF expression.
3194
        expression: UnwindExpression<T>,
3195
    },
3196
3197
    /// The `Restore` instruction represents both `DW_CFA_restore` and
3198
    /// `DW_CFA_restore_extended`.
3199
    ///
3200
    /// > 11. DW_CFA_restore
3201
    /// >
3202
    /// > The DW_CFA_restore instruction takes a single operand (encoded with
3203
    /// > the opcode) that represents a register number. The required action is
3204
    /// > to change the rule for the indicated register to the rule assigned it
3205
    /// > by the initial_instructions in the CIE.
3206
    Restore {
3207
        /// The register to be reset.
3208
        register: Register,
3209
    },
3210
3211
    // 6.4.2.4 Row State Instructions
3212
    /// > 1. DW_CFA_remember_state
3213
    /// >
3214
    /// > The DW_CFA_remember_state instruction takes no operands. The required
3215
    /// > action is to push the set of rules for every register onto an implicit
3216
    /// > stack.
3217
    RememberState,
3218
3219
    /// > 2. DW_CFA_restore_state
3220
    /// >
3221
    /// > The DW_CFA_restore_state instruction takes no operands. The required
3222
    /// > action is to pop the set of rules off the implicit stack and place
3223
    /// > them in the current row.
3224
    RestoreState,
3225
3226
    /// > DW_CFA_GNU_args_size
3227
    /// >
3228
    /// > GNU Extension
3229
    /// >
3230
    /// > The DW_CFA_GNU_args_size instruction takes an unsigned LEB128 operand
3231
    /// > representing an argument size. This instruction specifies the total of
3232
    /// > the size of the arguments which have been pushed onto the stack.
3233
    ArgsSize {
3234
        /// The size of the arguments which have been pushed onto the stack
3235
        size: u64,
3236
    },
3237
3238
    /// > DW_CFA_AARCH64_negate_ra_state
3239
    /// >
3240
    /// > AArch64 Extension
3241
    /// >
3242
    /// > The DW_CFA_AARCH64_negate_ra_state operation negates bit 0 of the
3243
    /// > RA_SIGN_STATE pseudo-register. It does not take any operands. The
3244
    /// > DW_CFA_AARCH64_negate_ra_state must not be mixed with other DWARF Register
3245
    /// > Rule Instructions on the RA_SIGN_STATE pseudo-register in one Common
3246
    /// > Information Entry (CIE) and Frame Descriptor Entry (FDE) program sequence.
3247
    NegateRaState,
3248
3249
    // 6.4.2.5 Padding Instruction
3250
    /// > 1. DW_CFA_nop
3251
    /// >
3252
    /// > The DW_CFA_nop instruction has no operands and no required actions. It
3253
    /// > is used as padding to make a CIE or FDE an appropriate size.
3254
    Nop,
3255
}
3256
3257
const CFI_INSTRUCTION_HIGH_BITS_MASK: u8 = 0b1100_0000;
3258
const CFI_INSTRUCTION_LOW_BITS_MASK: u8 = !CFI_INSTRUCTION_HIGH_BITS_MASK;
3259
3260
impl<T: ReaderOffset> CallFrameInstruction<T> {
3261
0
    fn parse<R: Reader<Offset = T>>(
3262
0
        input: &mut R,
3263
0
        address_encoding: Option<DwEhPe>,
3264
0
        parameters: &PointerEncodingParameters<'_, R>,
3265
0
        vendor: Vendor,
3266
0
    ) -> Result<CallFrameInstruction<T>> {
3267
0
        let instruction = input.read_u8()?;
3268
0
        let high_bits = instruction & CFI_INSTRUCTION_HIGH_BITS_MASK;
3269
3270
0
        if high_bits == constants::DW_CFA_advance_loc.0 {
3271
0
            let delta = instruction & CFI_INSTRUCTION_LOW_BITS_MASK;
3272
0
            return Ok(CallFrameInstruction::AdvanceLoc {
3273
0
                delta: u32::from(delta),
3274
0
            });
3275
0
        }
3276
3277
0
        if high_bits == constants::DW_CFA_offset.0 {
3278
0
            let register = Register((instruction & CFI_INSTRUCTION_LOW_BITS_MASK).into());
3279
0
            let offset = input.read_uleb128()?;
3280
0
            return Ok(CallFrameInstruction::Offset {
3281
0
                register,
3282
0
                factored_offset: offset,
3283
0
            });
3284
0
        }
3285
3286
0
        if high_bits == constants::DW_CFA_restore.0 {
3287
0
            let register = Register((instruction & CFI_INSTRUCTION_LOW_BITS_MASK).into());
3288
0
            return Ok(CallFrameInstruction::Restore { register });
3289
0
        }
3290
3291
0
        debug_assert_eq!(high_bits, 0);
3292
0
        let instruction = constants::DwCfa(instruction);
3293
3294
0
        match instruction {
3295
0
            constants::DW_CFA_nop => Ok(CallFrameInstruction::Nop),
3296
3297
            constants::DW_CFA_set_loc => {
3298
0
                let address = if let Some(encoding) = address_encoding {
3299
0
                    parse_encoded_pointer(encoding, parameters, input)?.direct()?
3300
                } else {
3301
0
                    input.read_address(parameters.address_size)?
3302
                };
3303
0
                Ok(CallFrameInstruction::SetLoc { address })
3304
            }
3305
3306
            constants::DW_CFA_advance_loc1 => {
3307
0
                let delta = input.read_u8()?;
3308
0
                Ok(CallFrameInstruction::AdvanceLoc {
3309
0
                    delta: u32::from(delta),
3310
0
                })
3311
            }
3312
3313
            constants::DW_CFA_advance_loc2 => {
3314
0
                let delta = input.read_u16()?;
3315
0
                Ok(CallFrameInstruction::AdvanceLoc {
3316
0
                    delta: u32::from(delta),
3317
0
                })
3318
            }
3319
3320
            constants::DW_CFA_advance_loc4 => {
3321
0
                let delta = input.read_u32()?;
3322
0
                Ok(CallFrameInstruction::AdvanceLoc { delta })
3323
            }
3324
3325
            constants::DW_CFA_offset_extended => {
3326
0
                let register = input.read_uleb128().and_then(Register::from_u64)?;
3327
0
                let offset = input.read_uleb128()?;
3328
0
                Ok(CallFrameInstruction::Offset {
3329
0
                    register,
3330
0
                    factored_offset: offset,
3331
0
                })
3332
            }
3333
3334
            constants::DW_CFA_restore_extended => {
3335
0
                let register = input.read_uleb128().and_then(Register::from_u64)?;
3336
0
                Ok(CallFrameInstruction::Restore { register })
3337
            }
3338
3339
            constants::DW_CFA_undefined => {
3340
0
                let register = input.read_uleb128().and_then(Register::from_u64)?;
3341
0
                Ok(CallFrameInstruction::Undefined { register })
3342
            }
3343
3344
            constants::DW_CFA_same_value => {
3345
0
                let register = input.read_uleb128().and_then(Register::from_u64)?;
3346
0
                Ok(CallFrameInstruction::SameValue { register })
3347
            }
3348
3349
            constants::DW_CFA_register => {
3350
0
                let dest = input.read_uleb128().and_then(Register::from_u64)?;
3351
0
                let src = input.read_uleb128().and_then(Register::from_u64)?;
3352
0
                Ok(CallFrameInstruction::Register {
3353
0
                    dest_register: dest,
3354
0
                    src_register: src,
3355
0
                })
3356
            }
3357
3358
0
            constants::DW_CFA_remember_state => Ok(CallFrameInstruction::RememberState),
3359
3360
0
            constants::DW_CFA_restore_state => Ok(CallFrameInstruction::RestoreState),
3361
3362
            constants::DW_CFA_def_cfa => {
3363
0
                let register = input.read_uleb128().and_then(Register::from_u64)?;
3364
0
                let offset = input.read_uleb128()?;
3365
0
                Ok(CallFrameInstruction::DefCfa { register, offset })
3366
            }
3367
3368
            constants::DW_CFA_def_cfa_register => {
3369
0
                let register = input.read_uleb128().and_then(Register::from_u64)?;
3370
0
                Ok(CallFrameInstruction::DefCfaRegister { register })
3371
            }
3372
3373
            constants::DW_CFA_def_cfa_offset => {
3374
0
                let offset = input.read_uleb128()?;
3375
0
                Ok(CallFrameInstruction::DefCfaOffset { offset })
3376
            }
3377
3378
            constants::DW_CFA_def_cfa_expression => {
3379
0
                let length = input.read_uleb128().and_then(R::Offset::from_u64)?;
3380
0
                let offset = input.offset_from(parameters.section);
3381
0
                input.skip(length)?;
3382
0
                Ok(CallFrameInstruction::DefCfaExpression {
3383
0
                    expression: UnwindExpression { offset, length },
3384
0
                })
3385
            }
3386
3387
            constants::DW_CFA_expression => {
3388
0
                let register = input.read_uleb128().and_then(Register::from_u64)?;
3389
0
                let length = input.read_uleb128().and_then(R::Offset::from_u64)?;
3390
0
                let offset = input.offset_from(parameters.section);
3391
0
                input.skip(length)?;
3392
0
                Ok(CallFrameInstruction::Expression {
3393
0
                    register,
3394
0
                    expression: UnwindExpression { offset, length },
3395
0
                })
3396
            }
3397
3398
            constants::DW_CFA_offset_extended_sf => {
3399
0
                let register = input.read_uleb128().and_then(Register::from_u64)?;
3400
0
                let offset = input.read_sleb128()?;
3401
0
                Ok(CallFrameInstruction::OffsetExtendedSf {
3402
0
                    register,
3403
0
                    factored_offset: offset,
3404
0
                })
3405
            }
3406
3407
            constants::DW_CFA_def_cfa_sf => {
3408
0
                let register = input.read_uleb128().and_then(Register::from_u64)?;
3409
0
                let offset = input.read_sleb128()?;
3410
0
                Ok(CallFrameInstruction::DefCfaSf {
3411
0
                    register,
3412
0
                    factored_offset: offset,
3413
0
                })
3414
            }
3415
3416
            constants::DW_CFA_def_cfa_offset_sf => {
3417
0
                let offset = input.read_sleb128()?;
3418
0
                Ok(CallFrameInstruction::DefCfaOffsetSf {
3419
0
                    factored_offset: offset,
3420
0
                })
3421
            }
3422
3423
            constants::DW_CFA_val_offset => {
3424
0
                let register = input.read_uleb128().and_then(Register::from_u64)?;
3425
0
                let offset = input.read_uleb128()?;
3426
0
                Ok(CallFrameInstruction::ValOffset {
3427
0
                    register,
3428
0
                    factored_offset: offset,
3429
0
                })
3430
            }
3431
3432
            constants::DW_CFA_val_offset_sf => {
3433
0
                let register = input.read_uleb128().and_then(Register::from_u64)?;
3434
0
                let offset = input.read_sleb128()?;
3435
0
                Ok(CallFrameInstruction::ValOffsetSf {
3436
0
                    register,
3437
0
                    factored_offset: offset,
3438
0
                })
3439
            }
3440
3441
            constants::DW_CFA_val_expression => {
3442
0
                let register = input.read_uleb128().and_then(Register::from_u64)?;
3443
0
                let length = input.read_uleb128().and_then(R::Offset::from_u64)?;
3444
0
                let offset = input.offset_from(parameters.section);
3445
0
                input.skip(length)?;
3446
0
                Ok(CallFrameInstruction::ValExpression {
3447
0
                    register,
3448
0
                    expression: UnwindExpression { offset, length },
3449
0
                })
3450
            }
3451
3452
            constants::DW_CFA_GNU_args_size => {
3453
0
                let size = input.read_uleb128()?;
3454
0
                Ok(CallFrameInstruction::ArgsSize { size })
3455
            }
3456
3457
0
            constants::DW_CFA_AARCH64_negate_ra_state if vendor == Vendor::AArch64 => {
3458
0
                Ok(CallFrameInstruction::NegateRaState)
3459
            }
3460
3461
0
            otherwise => Err(Error::UnknownCallFrameInstruction(otherwise)),
3462
        }
3463
0
    }
3464
}
3465
3466
/// A lazy iterator parsing call frame instructions.
3467
///
3468
/// Can be [used with
3469
/// `FallibleIterator`](./index.html#using-with-fallibleiterator).
3470
#[derive(Clone, Debug)]
3471
pub struct CallFrameInstructionIter<'a, R: Reader> {
3472
    input: R,
3473
    address_encoding: Option<constants::DwEhPe>,
3474
    parameters: PointerEncodingParameters<'a, R>,
3475
    vendor: Vendor,
3476
}
3477
3478
impl<'a, R: Reader> CallFrameInstructionIter<'a, R> {
3479
    /// Parse the next call frame instruction.
3480
0
    pub fn next(&mut self) -> Result<Option<CallFrameInstruction<R::Offset>>> {
3481
0
        if self.input.is_empty() {
3482
0
            return Ok(None);
3483
0
        }
3484
3485
0
        match CallFrameInstruction::parse(
3486
0
            &mut self.input,
3487
0
            self.address_encoding,
3488
0
            &self.parameters,
3489
0
            self.vendor,
3490
0
        ) {
3491
0
            Ok(instruction) => Ok(Some(instruction)),
3492
0
            Err(e) => {
3493
0
                self.input.empty();
3494
0
                Err(e)
3495
            }
3496
        }
3497
0
    }
3498
}
3499
3500
#[cfg(feature = "fallible-iterator")]
3501
impl<'a, R: Reader> fallible_iterator::FallibleIterator for CallFrameInstructionIter<'a, R> {
3502
    type Item = CallFrameInstruction<R::Offset>;
3503
    type Error = Error;
3504
3505
    fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
3506
        CallFrameInstructionIter::next(self)
3507
    }
3508
}
3509
3510
/// The location of a DWARF expression within an unwind section.
3511
///
3512
/// This is stored as an offset and length within the section instead of as a
3513
/// `Reader` to avoid lifetime issues when reusing [`UnwindContext`].
3514
///
3515
/// # Example
3516
/// ```
3517
/// # use gimli::{EhFrame, EndianSlice, NativeEndian, Error, FrameDescriptionEntry, UnwindExpression, EvaluationResult};
3518
/// # fn foo() -> Result<(), Error> {
3519
/// # let eh_frame: EhFrame<EndianSlice<NativeEndian>> = unreachable!();
3520
/// # let fde: FrameDescriptionEntry<EndianSlice<NativeEndian>> = unimplemented!();
3521
/// # let unwind_expression: UnwindExpression<_> = unimplemented!();
3522
/// let expression = unwind_expression.get(&eh_frame)?;
3523
/// let mut evaluation = expression.evaluation(fde.cie().encoding());
3524
/// let mut result = evaluation.evaluate()?;
3525
/// loop {
3526
///   match result {
3527
///      EvaluationResult::Complete => break,
3528
///      // Provide information to the evaluation.
3529
///      _ => { unimplemented!()}
3530
///   }
3531
/// }
3532
/// let value = evaluation.value_result();
3533
/// # Ok(())
3534
/// # }
3535
/// ```
3536
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3537
pub struct UnwindExpression<T: ReaderOffset> {
3538
    /// The offset of the expression within the section.
3539
    pub offset: T,
3540
    /// The length of the expression.
3541
    pub length: T,
3542
}
3543
3544
impl<T: ReaderOffset> UnwindExpression<T> {
3545
    /// Get the expression from the section.
3546
    ///
3547
    /// The offset and length were previously validated when the
3548
    /// `UnwindExpression` was created, so this should not fail.
3549
0
    pub fn get<R, S>(&self, section: &S) -> Result<Expression<R>>
3550
0
    where
3551
0
        R: Reader<Offset = T>,
3552
0
        S: UnwindSection<R>,
3553
    {
3554
0
        let input = &mut section.section().clone();
3555
0
        input.skip(self.offset)?;
3556
0
        let data = input.split(self.length)?;
3557
0
        Ok(Expression(data))
3558
0
    }
3559
}
3560
3561
/// Parse a `DW_EH_PE_*` pointer encoding.
3562
#[doc(hidden)]
3563
#[inline]
3564
0
fn parse_pointer_encoding<R: Reader>(input: &mut R) -> Result<constants::DwEhPe> {
3565
0
    let eh_pe = input.read_u8()?;
3566
0
    let eh_pe = constants::DwEhPe(eh_pe);
3567
3568
0
    if eh_pe.is_valid_encoding() {
3569
0
        Ok(eh_pe)
3570
    } else {
3571
0
        Err(Error::UnknownPointerEncoding(eh_pe))
3572
    }
3573
0
}
3574
3575
/// A decoded pointer.
3576
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
3577
pub enum Pointer {
3578
    /// This value is the decoded pointer value.
3579
    Direct(u64),
3580
3581
    /// This value is *not* the pointer value, but points to the address of
3582
    /// where the real pointer value lives. In other words, deref this pointer
3583
    /// to get the real pointer value.
3584
    ///
3585
    /// Chase this pointer at your own risk: do you trust the DWARF data it came
3586
    /// from?
3587
    Indirect(u64),
3588
}
3589
3590
impl Default for Pointer {
3591
    #[inline]
3592
0
    fn default() -> Self {
3593
0
        Pointer::Direct(0)
3594
0
    }
3595
}
3596
3597
impl Pointer {
3598
    #[inline]
3599
0
    fn new(encoding: constants::DwEhPe, address: u64) -> Pointer {
3600
0
        if encoding.is_indirect() {
3601
0
            Pointer::Indirect(address)
3602
        } else {
3603
0
            Pointer::Direct(address)
3604
        }
3605
0
    }
3606
3607
    /// Return the direct pointer value.
3608
    #[inline]
3609
0
    pub fn direct(self) -> Result<u64> {
3610
0
        match self {
3611
0
            Pointer::Direct(p) => Ok(p),
3612
0
            Pointer::Indirect(_) => Err(Error::UnsupportedPointerEncoding),
3613
        }
3614
0
    }
3615
3616
    /// Return the pointer value, discarding indirectness information.
3617
    #[inline]
3618
0
    pub fn pointer(self) -> u64 {
3619
0
        match self {
3620
0
            Pointer::Direct(p) | Pointer::Indirect(p) => p,
3621
        }
3622
0
    }
3623
}
3624
3625
#[derive(Clone, Debug)]
3626
struct PointerEncodingParameters<'a, R: Reader> {
3627
    bases: &'a SectionBaseAddresses,
3628
    func_base: Option<u64>,
3629
    address_size: u8,
3630
    section: &'a R,
3631
}
3632
3633
0
fn parse_encoded_pointer<R: Reader>(
3634
0
    encoding: constants::DwEhPe,
3635
0
    parameters: &PointerEncodingParameters<'_, R>,
3636
0
    input: &mut R,
3637
0
) -> Result<Pointer> {
3638
    // TODO: check this once only in parse_pointer_encoding
3639
0
    if !encoding.is_valid_encoding() {
3640
0
        return Err(Error::UnknownPointerEncoding(encoding));
3641
0
    }
3642
3643
0
    if encoding == constants::DW_EH_PE_omit {
3644
0
        return Err(Error::CannotParseOmitPointerEncoding);
3645
0
    }
3646
3647
0
    let base = match encoding.application() {
3648
0
        constants::DW_EH_PE_absptr => 0,
3649
        constants::DW_EH_PE_pcrel => {
3650
0
            if let Some(section_base) = parameters.bases.section {
3651
0
                let offset_from_section = input.offset_from(parameters.section);
3652
0
                section_base
3653
0
                    .wrapping_add_sized(offset_from_section.into_u64(), parameters.address_size)
3654
            } else {
3655
0
                return Err(Error::PcRelativePointerButSectionBaseIsUndefined);
3656
            }
3657
        }
3658
        constants::DW_EH_PE_textrel => {
3659
0
            if let Some(text) = parameters.bases.text {
3660
0
                text
3661
            } else {
3662
0
                return Err(Error::TextRelativePointerButTextBaseIsUndefined);
3663
            }
3664
        }
3665
        constants::DW_EH_PE_datarel => {
3666
0
            if let Some(data) = parameters.bases.data {
3667
0
                data
3668
            } else {
3669
0
                return Err(Error::DataRelativePointerButDataBaseIsUndefined);
3670
            }
3671
        }
3672
        constants::DW_EH_PE_funcrel => {
3673
0
            if let Some(func) = parameters.func_base {
3674
0
                func
3675
            } else {
3676
0
                return Err(Error::FuncRelativePointerInBadContext);
3677
            }
3678
        }
3679
0
        constants::DW_EH_PE_aligned => return Err(Error::UnsupportedPointerEncoding),
3680
0
        _ => unreachable!(),
3681
    };
3682
3683
0
    let offset = parse_encoded_value(encoding, parameters, input)?;
3684
0
    Ok(Pointer::new(
3685
0
        encoding,
3686
0
        base.wrapping_add_sized(offset, parameters.address_size),
3687
0
    ))
3688
0
}
3689
3690
0
fn parse_encoded_value<R: Reader>(
3691
0
    encoding: constants::DwEhPe,
3692
0
    parameters: &PointerEncodingParameters<'_, R>,
3693
0
    input: &mut R,
3694
0
) -> Result<u64> {
3695
0
    match encoding.format() {
3696
        // Unsigned variants.
3697
0
        constants::DW_EH_PE_absptr => input.read_address(parameters.address_size),
3698
0
        constants::DW_EH_PE_uleb128 => input.read_uleb128(),
3699
0
        constants::DW_EH_PE_udata2 => input.read_u16().map(u64::from),
3700
0
        constants::DW_EH_PE_udata4 => input.read_u32().map(u64::from),
3701
0
        constants::DW_EH_PE_udata8 => input.read_u64(),
3702
3703
        // Signed variants. Here we sign extend the values (happens by
3704
        // default when casting a signed integer to a larger range integer
3705
        // in Rust), return them as u64, and rely on wrapping addition to do
3706
        // the right thing when adding these offsets to their bases.
3707
0
        constants::DW_EH_PE_sleb128 => input.read_sleb128().map(|a| a as u64),
3708
0
        constants::DW_EH_PE_sdata2 => input.read_i16().map(|a| a as u64),
3709
0
        constants::DW_EH_PE_sdata4 => input.read_i32().map(|a| a as u64),
3710
0
        constants::DW_EH_PE_sdata8 => input.read_i64().map(|a| a as u64),
3711
3712
        // That was all of the valid encoding formats.
3713
0
        _ => unreachable!(),
3714
    }
3715
0
}
3716
3717
#[cfg(test)]
3718
mod tests {
3719
    use super::*;
3720
    use super::{parse_cfi_entry, AugmentationData, RegisterRuleMap, UnwindContext};
3721
    use crate::common::Format;
3722
    use crate::constants;
3723
    use crate::endianity::{BigEndian, Endianity, LittleEndian, NativeEndian};
3724
    use crate::read::{
3725
        EndianSlice, Error, Pointer, ReaderOffsetId, Result, Section as ReadSection,
3726
    };
3727
    use crate::test_util::GimliSectionMethods;
3728
    use alloc::boxed::Box;
3729
    use alloc::vec::Vec;
3730
    use core::marker::PhantomData;
3731
    use core::mem;
3732
    use test_assembler::{Endian, Label, LabelMaker, LabelOrNum, Section, ToLabelOrNum};
3733
3734
    // Ensure each test tries to read the same section kind that it wrote.
3735
    #[derive(Clone, Copy)]
3736
    struct SectionKind<Section>(PhantomData<Section>);
3737
3738
    impl<T> SectionKind<T> {
3739
        fn endian<'input, E>(self) -> Endian
3740
        where
3741
            E: Endianity,
3742
            T: UnwindSection<EndianSlice<'input, E>>,
3743
            T::Offset: UnwindOffset<usize>,
3744
        {
3745
            if E::default().is_big_endian() {
3746
                Endian::Big
3747
            } else {
3748
                Endian::Little
3749
            }
3750
        }
3751
3752
        fn section<'input, E>(self, contents: &'input [u8]) -> T
3753
        where
3754
            E: Endianity,
3755
            T: UnwindSection<EndianSlice<'input, E>> + ReadSection<EndianSlice<'input, E>>,
3756
            T::Offset: UnwindOffset<usize>,
3757
        {
3758
            EndianSlice::new(contents, E::default()).into()
3759
        }
3760
    }
3761
3762
    fn debug_frame_le<'a>() -> SectionKind<DebugFrame<EndianSlice<'a, LittleEndian>>> {
3763
        SectionKind(PhantomData)
3764
    }
3765
3766
    fn debug_frame_be<'a>() -> SectionKind<DebugFrame<EndianSlice<'a, BigEndian>>> {
3767
        SectionKind(PhantomData)
3768
    }
3769
3770
    fn eh_frame_le<'a>() -> SectionKind<EhFrame<EndianSlice<'a, LittleEndian>>> {
3771
        SectionKind(PhantomData)
3772
    }
3773
3774
    fn parse_fde<Section, O, F, R>(
3775
        section: Section,
3776
        input: &mut R,
3777
        get_cie: F,
3778
    ) -> Result<FrameDescriptionEntry<R>>
3779
    where
3780
        R: Reader,
3781
        Section: UnwindSection<R, Offset = O>,
3782
        O: UnwindOffset<R::Offset>,
3783
        F: FnMut(&Section, &BaseAddresses, O) -> Result<CommonInformationEntry<R>>,
3784
    {
3785
        let bases = Default::default();
3786
        match parse_cfi_entry(&bases, &section, input) {
3787
            Ok(Some(CieOrFde::Fde(partial))) => partial.parse(get_cie),
3788
            Ok(_) => Err(Error::NoEntryAtGivenOffset),
3789
            Err(e) => Err(e),
3790
        }
3791
    }
3792
3793
    // Mixin methods for `Section` to help define binary test data.
3794
3795
    trait CfiSectionMethods: GimliSectionMethods {
3796
        fn cie<'aug, 'input, E, T>(
3797
            self,
3798
            _kind: SectionKind<T>,
3799
            augmentation: Option<&'aug str>,
3800
            cie: &mut CommonInformationEntry<EndianSlice<'input, E>>,
3801
        ) -> Self
3802
        where
3803
            E: Endianity,
3804
            T: UnwindSection<EndianSlice<'input, E>>,
3805
            T::Offset: UnwindOffset;
3806
        fn fde<'a, 'input, E, T, L>(
3807
            self,
3808
            _kind: SectionKind<T>,
3809
            cie_offset: L,
3810
            fde: &mut FrameDescriptionEntry<EndianSlice<'input, E>>,
3811
        ) -> Self
3812
        where
3813
            E: Endianity,
3814
            T: UnwindSection<EndianSlice<'input, E>>,
3815
            T::Offset: UnwindOffset,
3816
            L: ToLabelOrNum<'a, u64>;
3817
    }
3818
3819
    impl CfiSectionMethods for Section {
3820
        fn cie<'aug, 'input, E, T>(
3821
            self,
3822
            _kind: SectionKind<T>,
3823
            augmentation: Option<&'aug str>,
3824
            cie: &mut CommonInformationEntry<EndianSlice<'input, E>>,
3825
        ) -> Self
3826
        where
3827
            E: Endianity,
3828
            T: UnwindSection<EndianSlice<'input, E>>,
3829
            T::Offset: UnwindOffset,
3830
        {
3831
            cie.offset = self.size() as _;
3832
            let length = Label::new();
3833
            let start = Label::new();
3834
            let end = Label::new();
3835
3836
            let section = match cie.format {
3837
                Format::Dwarf32 => self.D32(&length).mark(&start).D32(0xffff_ffff),
3838
                Format::Dwarf64 => {
3839
                    let section = self.D32(0xffff_ffff);
3840
                    section.D64(&length).mark(&start).D64(0xffff_ffff_ffff_ffff)
3841
                }
3842
            };
3843
3844
            let mut section = section.D8(cie.version);
3845
3846
            if let Some(augmentation) = augmentation {
3847
                section = section.append_bytes(augmentation.as_bytes());
3848
            }
3849
3850
            // Null terminator for augmentation string.
3851
            let section = section.D8(0);
3852
3853
            let section = if T::has_address_and_segment_sizes(cie.version) {
3854
                section.D8(cie.address_size).D8(0)
3855
            } else {
3856
                section
3857
            };
3858
3859
            let section = section
3860
                .uleb(cie.code_alignment_factor)
3861
                .sleb(cie.data_alignment_factor)
3862
                .uleb(cie.return_address_register.0.into())
3863
                .append_bytes(cie.initial_instructions.slice())
3864
                .mark(&end);
3865
3866
            cie.length = (&end - &start) as usize;
3867
            length.set_const(cie.length as u64);
3868
3869
            section
3870
        }
3871
3872
        fn fde<'a, 'input, E, T, L>(
3873
            self,
3874
            _kind: SectionKind<T>,
3875
            cie_offset: L,
3876
            fde: &mut FrameDescriptionEntry<EndianSlice<'input, E>>,
3877
        ) -> Self
3878
        where
3879
            E: Endianity,
3880
            T: UnwindSection<EndianSlice<'input, E>>,
3881
            T::Offset: UnwindOffset,
3882
            L: ToLabelOrNum<'a, u64>,
3883
        {
3884
            fde.offset = self.size() as _;
3885
            let length = Label::new();
3886
            let start = Label::new();
3887
            let end = Label::new();
3888
3889
            assert_eq!(fde.format, fde.cie.format);
3890
3891
            let section = match T::cie_offset_encoding(fde.format) {
3892
                CieOffsetEncoding::U32 => {
3893
                    let section = self.D32(&length).mark(&start);
3894
                    match cie_offset.to_labelornum() {
3895
                        LabelOrNum::Label(ref l) => section.D32(l),
3896
                        LabelOrNum::Num(o) => section.D32(o as u32),
3897
                    }
3898
                }
3899
                CieOffsetEncoding::U64 => {
3900
                    let section = self.D32(0xffff_ffff);
3901
                    section.D64(&length).mark(&start).D64(cie_offset)
3902
                }
3903
            };
3904
3905
            let section = match fde.cie.address_size {
3906
                4 => section
3907
                    .D32(fde.initial_address() as u32)
3908
                    .D32(fde.len() as u32),
3909
                8 => section.D64(fde.initial_address()).D64(fde.len()),
3910
                x => panic!("Unsupported address size: {}", x),
3911
            };
3912
3913
            let section = if let Some(ref augmentation) = fde.augmentation {
3914
                let cie_aug = fde
3915
                    .cie
3916
                    .augmentation
3917
                    .expect("FDE has augmentation, but CIE doesn't");
3918
3919
                if let Some(lsda) = augmentation.lsda {
3920
                    // We only support writing `DW_EH_PE_absptr` here.
3921
                    assert_eq!(
3922
                        cie_aug
3923
                            .lsda
3924
                            .expect("FDE has lsda, but CIE doesn't")
3925
                            .format(),
3926
                        constants::DW_EH_PE_absptr
3927
                    );
3928
3929
                    // Augmentation data length
3930
                    let section = section.uleb(u64::from(fde.cie.address_size));
3931
                    match fde.cie.address_size {
3932
                        4 => section.D32({
3933
                            let x: u64 = lsda.pointer();
3934
                            x as u32
3935
                        }),
3936
                        8 => section.D64({
3937
                            let x: u64 = lsda.pointer();
3938
                            x
3939
                        }),
3940
                        x => panic!("Unsupported address size: {}", x),
3941
                    }
3942
                } else {
3943
                    // Even if we don't have any augmentation data, if there is
3944
                    // an augmentation defined, we need to put the length in.
3945
                    section.uleb(0)
3946
                }
3947
            } else {
3948
                section
3949
            };
3950
3951
            let section = section.append_bytes(fde.instructions.slice()).mark(&end);
3952
3953
            fde.length = (&end - &start) as usize;
3954
            length.set_const(fde.length as u64);
3955
3956
            section
3957
        }
3958
    }
3959
3960
    trait ResultExt {
3961
        fn map_eof(self, input: &[u8]) -> Self;
3962
    }
3963
3964
    impl<T> ResultExt for Result<T> {
3965
        fn map_eof(self, input: &[u8]) -> Self {
3966
            match self {
3967
                Err(Error::UnexpectedEof(id)) => {
3968
                    let id = ReaderOffsetId(id.0 - input.as_ptr() as u64);
3969
                    Err(Error::UnexpectedEof(id))
3970
                }
3971
                r => r,
3972
            }
3973
        }
3974
    }
3975
3976
    fn assert_parse_cie<'input, E>(
3977
        kind: SectionKind<DebugFrame<EndianSlice<'input, E>>>,
3978
        section: Section,
3979
        address_size: u8,
3980
        expected: Result<(
3981
            EndianSlice<'input, E>,
3982
            CommonInformationEntry<EndianSlice<'input, E>>,
3983
        )>,
3984
    ) where
3985
        E: Endianity,
3986
    {
3987
        let section = section.get_contents().unwrap();
3988
        let mut debug_frame = kind.section(&section);
3989
        debug_frame.set_address_size(address_size);
3990
        let input = &mut EndianSlice::new(&section, E::default());
3991
        let bases = Default::default();
3992
        let result = CommonInformationEntry::parse(&bases, &debug_frame, input);
3993
        let result = result.map(|cie| (*input, cie)).map_eof(&section);
3994
        assert_eq!(result, expected);
3995
    }
3996
3997
    #[test]
3998
    fn test_parse_cie_incomplete_length_32() {
3999
        let kind = debug_frame_le();
4000
        let section = Section::with_endian(kind.endian()).L16(5);
4001
        assert_parse_cie(
4002
            kind,
4003
            section,
4004
            8,
4005
            Err(Error::UnexpectedEof(ReaderOffsetId(0))),
4006
        );
4007
    }
4008
4009
    #[test]
4010
    fn test_parse_cie_incomplete_length_64() {
4011
        let kind = debug_frame_le();
4012
        let section = Section::with_endian(kind.endian())
4013
            .L32(0xffff_ffff)
4014
            .L32(12345);
4015
        assert_parse_cie(
4016
            kind,
4017
            section,
4018
            8,
4019
            Err(Error::UnexpectedEof(ReaderOffsetId(4))),
4020
        );
4021
    }
4022
4023
    #[test]
4024
    fn test_parse_cie_incomplete_id_32() {
4025
        let kind = debug_frame_be();
4026
        let section = Section::with_endian(kind.endian())
4027
            // The length is not large enough to contain the ID.
4028
            .B32(3)
4029
            .B32(0xffff_ffff);
4030
        assert_parse_cie(
4031
            kind,
4032
            section,
4033
            8,
4034
            Err(Error::UnexpectedEof(ReaderOffsetId(4))),
4035
        );
4036
    }
4037
4038
    #[test]
4039
    fn test_parse_cie_bad_id_32() {
4040
        let kind = debug_frame_be();
4041
        let section = Section::with_endian(kind.endian())
4042
            // Initial length
4043
            .B32(4)
4044
            // Not the CIE Id.
4045
            .B32(0xbad1_bad2);
4046
        assert_parse_cie(kind, section, 8, Err(Error::NotCieId));
4047
    }
4048
4049
    #[test]
4050
    fn test_parse_cie_32_bad_version() {
4051
        let mut cie = CommonInformationEntry {
4052
            offset: 0,
4053
            length: 0,
4054
            format: Format::Dwarf32,
4055
            version: 99,
4056
            augmentation: None,
4057
            address_size: 4,
4058
            code_alignment_factor: 1,
4059
            data_alignment_factor: 2,
4060
            return_address_register: Register(3),
4061
            initial_instructions: EndianSlice::new(&[], LittleEndian),
4062
        };
4063
4064
        let kind = debug_frame_le();
4065
        let section = Section::with_endian(kind.endian()).cie(kind, None, &mut cie);
4066
        assert_parse_cie(kind, section, 4, Err(Error::UnknownVersion(99)));
4067
    }
4068
4069
    #[test]
4070
    fn test_parse_cie_unknown_augmentation() {
4071
        let length = Label::new();
4072
        let start = Label::new();
4073
        let end = Label::new();
4074
4075
        let augmentation = "replicant";
4076
        let expected_rest = [1, 2, 3];
4077
4078
        let kind = debug_frame_le();
4079
        let section = Section::with_endian(kind.endian())
4080
            // Initial length
4081
            .L32(&length)
4082
            .mark(&start)
4083
            // CIE Id
4084
            .L32(0xffff_ffff)
4085
            // Version
4086
            .D8(4)
4087
            // Augmentation
4088
            .append_bytes(augmentation.as_bytes())
4089
            // Null terminator
4090
            .D8(0)
4091
            // Extra augmented data that we can't understand.
4092
            .L32(1)
4093
            .L32(2)
4094
            .L32(3)
4095
            .L32(4)
4096
            .L32(5)
4097
            .L32(6)
4098
            .mark(&end)
4099
            .append_bytes(&expected_rest);
4100
4101
        let expected_length = (&end - &start) as u64;
4102
        length.set_const(expected_length);
4103
4104
        assert_parse_cie(kind, section, 8, Err(Error::UnknownAugmentation));
4105
    }
4106
4107
    fn test_parse_cie(format: Format, version: u8, address_size: u8) {
4108
        let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9];
4109
        let expected_instrs: Vec<_> = (0..4).map(|_| constants::DW_CFA_nop.0).collect();
4110
4111
        let mut cie = CommonInformationEntry {
4112
            offset: 0,
4113
            length: 0,
4114
            format,
4115
            version,
4116
            augmentation: None,
4117
            address_size,
4118
            code_alignment_factor: 16,
4119
            data_alignment_factor: 32,
4120
            return_address_register: Register(1),
4121
            initial_instructions: EndianSlice::new(&expected_instrs, LittleEndian),
4122
        };
4123
4124
        let kind = debug_frame_le();
4125
        let section = Section::with_endian(kind.endian())
4126
            .cie(kind, None, &mut cie)
4127
            .append_bytes(&expected_rest);
4128
4129
        assert_parse_cie(
4130
            kind,
4131
            section,
4132
            address_size,
4133
            Ok((EndianSlice::new(&expected_rest, LittleEndian), cie)),
4134
        );
4135
    }
4136
4137
    #[test]
4138
    fn test_parse_cie_32_ok() {
4139
        test_parse_cie(Format::Dwarf32, 1, 4);
4140
        test_parse_cie(Format::Dwarf32, 1, 8);
4141
        test_parse_cie(Format::Dwarf32, 4, 4);
4142
        test_parse_cie(Format::Dwarf32, 4, 8);
4143
    }
4144
4145
    #[test]
4146
    fn test_parse_cie_64_ok() {
4147
        test_parse_cie(Format::Dwarf64, 1, 4);
4148
        test_parse_cie(Format::Dwarf64, 1, 8);
4149
        test_parse_cie(Format::Dwarf64, 4, 4);
4150
        test_parse_cie(Format::Dwarf64, 4, 8);
4151
    }
4152
4153
    #[test]
4154
    fn test_parse_cie_length_too_big() {
4155
        let expected_instrs: Vec<_> = (0..13).map(|_| constants::DW_CFA_nop.0).collect();
4156
4157
        let mut cie = CommonInformationEntry {
4158
            offset: 0,
4159
            length: 0,
4160
            format: Format::Dwarf32,
4161
            version: 4,
4162
            augmentation: None,
4163
            address_size: 4,
4164
            code_alignment_factor: 0,
4165
            data_alignment_factor: 0,
4166
            return_address_register: Register(3),
4167
            initial_instructions: EndianSlice::new(&expected_instrs, LittleEndian),
4168
        };
4169
4170
        let kind = debug_frame_le();
4171
        let section = Section::with_endian(kind.endian()).cie(kind, None, &mut cie);
4172
4173
        let mut contents = section.get_contents().unwrap();
4174
4175
        // Overwrite the length to be too big.
4176
        contents[0] = 0;
4177
        contents[1] = 0;
4178
        contents[2] = 0;
4179
        contents[3] = 255;
4180
4181
        let debug_frame = DebugFrame::new(&contents, LittleEndian);
4182
        let bases = Default::default();
4183
        assert_eq!(
4184
            CommonInformationEntry::parse(
4185
                &bases,
4186
                &debug_frame,
4187
                &mut EndianSlice::new(&contents, LittleEndian)
4188
            )
4189
            .map_eof(&contents),
4190
            Err(Error::UnexpectedEof(ReaderOffsetId(4)))
4191
        );
4192
    }
4193
4194
    #[test]
4195
    fn test_parse_fde_incomplete_length_32() {
4196
        let kind = debug_frame_le();
4197
        let section = Section::with_endian(kind.endian()).L16(5);
4198
        let section = section.get_contents().unwrap();
4199
        let debug_frame = kind.section(&section);
4200
        let rest = &mut EndianSlice::new(&section, LittleEndian);
4201
        assert_eq!(
4202
            parse_fde(debug_frame, rest, UnwindSection::cie_from_offset).map_eof(&section),
4203
            Err(Error::UnexpectedEof(ReaderOffsetId(0)))
4204
        );
4205
    }
4206
4207
    #[test]
4208
    fn test_parse_fde_incomplete_length_64() {
4209
        let kind = debug_frame_le();
4210
        let section = Section::with_endian(kind.endian())
4211
            .L32(0xffff_ffff)
4212
            .L32(12345);
4213
        let section = section.get_contents().unwrap();
4214
        let debug_frame = kind.section(&section);
4215
        let rest = &mut EndianSlice::new(&section, LittleEndian);
4216
        assert_eq!(
4217
            parse_fde(debug_frame, rest, UnwindSection::cie_from_offset).map_eof(&section),
4218
            Err(Error::UnexpectedEof(ReaderOffsetId(4)))
4219
        );
4220
    }
4221
4222
    #[test]
4223
    fn test_parse_fde_incomplete_cie_pointer_32() {
4224
        let kind = debug_frame_be();
4225
        let section = Section::with_endian(kind.endian())
4226
            // The length is not large enough to contain the CIE pointer.
4227
            .B32(3)
4228
            .B32(1994);
4229
        let section = section.get_contents().unwrap();
4230
        let debug_frame = kind.section(&section);
4231
        let rest = &mut EndianSlice::new(&section, BigEndian);
4232
        assert_eq!(
4233
            parse_fde(debug_frame, rest, UnwindSection::cie_from_offset).map_eof(&section),
4234
            Err(Error::UnexpectedEof(ReaderOffsetId(4)))
4235
        );
4236
    }
4237
4238
    #[test]
4239
    fn test_parse_fde_32_ok() {
4240
        let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9];
4241
        let cie_offset = 0xbad0_bad1;
4242
        let expected_instrs: Vec<_> = (0..7).map(|_| constants::DW_CFA_nop.0).collect();
4243
4244
        let cie = CommonInformationEntry {
4245
            offset: 0,
4246
            length: 100,
4247
            format: Format::Dwarf32,
4248
            version: 4,
4249
            augmentation: None,
4250
            // DWARF32 with a 64 bit address size! Holy moly!
4251
            address_size: 8,
4252
            code_alignment_factor: 3,
4253
            data_alignment_factor: 2,
4254
            return_address_register: Register(1),
4255
            initial_instructions: EndianSlice::new(&[], LittleEndian),
4256
        };
4257
4258
        let mut fde = FrameDescriptionEntry {
4259
            offset: 0,
4260
            length: 0,
4261
            format: Format::Dwarf32,
4262
            cie: cie.clone(),
4263
            initial_address: 0xfeed_beef,
4264
            address_range: 39,
4265
            augmentation: None,
4266
            instructions: EndianSlice::new(&expected_instrs, LittleEndian),
4267
        };
4268
4269
        let kind = debug_frame_le();
4270
        let section = Section::with_endian(kind.endian())
4271
            .fde(kind, cie_offset, &mut fde)
4272
            .append_bytes(&expected_rest);
4273
4274
        let section = section.get_contents().unwrap();
4275
        let debug_frame = kind.section(&section);
4276
        let rest = &mut EndianSlice::new(&section, LittleEndian);
4277
4278
        let get_cie = |_: &_, _: &_, offset| {
4279
            assert_eq!(offset, DebugFrameOffset(cie_offset as usize));
4280
            Ok(cie.clone())
4281
        };
4282
4283
        assert_eq!(parse_fde(debug_frame, rest, get_cie), Ok(fde));
4284
        assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
4285
    }
4286
4287
    #[test]
4288
    fn test_parse_fde_64_ok() {
4289
        let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9];
4290
        let cie_offset = 0xbad0_bad1;
4291
        let expected_instrs: Vec<_> = (0..7).map(|_| constants::DW_CFA_nop.0).collect();
4292
4293
        let cie = CommonInformationEntry {
4294
            offset: 0,
4295
            length: 100,
4296
            format: Format::Dwarf64,
4297
            version: 4,
4298
            augmentation: None,
4299
            address_size: 8,
4300
            code_alignment_factor: 3,
4301
            data_alignment_factor: 2,
4302
            return_address_register: Register(1),
4303
            initial_instructions: EndianSlice::new(&[], LittleEndian),
4304
        };
4305
4306
        let mut fde = FrameDescriptionEntry {
4307
            offset: 0,
4308
            length: 0,
4309
            format: Format::Dwarf64,
4310
            cie: cie.clone(),
4311
            initial_address: 0xfeed_beef,
4312
            address_range: 999,
4313
            augmentation: None,
4314
            instructions: EndianSlice::new(&expected_instrs, LittleEndian),
4315
        };
4316
4317
        let kind = debug_frame_le();
4318
        let section = Section::with_endian(kind.endian())
4319
            .fde(kind, cie_offset, &mut fde)
4320
            .append_bytes(&expected_rest);
4321
4322
        let section = section.get_contents().unwrap();
4323
        let debug_frame = kind.section(&section);
4324
        let rest = &mut EndianSlice::new(&section, LittleEndian);
4325
4326
        let get_cie = |_: &_, _: &_, offset| {
4327
            assert_eq!(offset, DebugFrameOffset(cie_offset as usize));
4328
            Ok(cie.clone())
4329
        };
4330
4331
        assert_eq!(parse_fde(debug_frame, rest, get_cie), Ok(fde));
4332
        assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
4333
    }
4334
4335
    #[test]
4336
    fn test_parse_cfi_entry_on_cie_32_ok() {
4337
        let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9];
4338
        let expected_instrs: Vec<_> = (0..4).map(|_| constants::DW_CFA_nop.0).collect();
4339
4340
        let mut cie = CommonInformationEntry {
4341
            offset: 0,
4342
            length: 0,
4343
            format: Format::Dwarf32,
4344
            version: 4,
4345
            augmentation: None,
4346
            address_size: 4,
4347
            code_alignment_factor: 16,
4348
            data_alignment_factor: 32,
4349
            return_address_register: Register(1),
4350
            initial_instructions: EndianSlice::new(&expected_instrs, BigEndian),
4351
        };
4352
4353
        let kind = debug_frame_be();
4354
        let section = Section::with_endian(kind.endian())
4355
            .cie(kind, None, &mut cie)
4356
            .append_bytes(&expected_rest);
4357
        let section = section.get_contents().unwrap();
4358
        let debug_frame = kind.section(&section);
4359
        let rest = &mut EndianSlice::new(&section, BigEndian);
4360
4361
        let bases = Default::default();
4362
        assert_eq!(
4363
            parse_cfi_entry(&bases, &debug_frame, rest),
4364
            Ok(Some(CieOrFde::Cie(cie)))
4365
        );
4366
        assert_eq!(*rest, EndianSlice::new(&expected_rest, BigEndian));
4367
    }
4368
4369
    #[test]
4370
    fn test_parse_cfi_entry_on_fde_32_ok() {
4371
        let cie_offset = 0x1234_5678;
4372
        let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9];
4373
        let expected_instrs: Vec<_> = (0..4).map(|_| constants::DW_CFA_nop.0).collect();
4374
4375
        let cie = CommonInformationEntry {
4376
            offset: 0,
4377
            length: 0,
4378
            format: Format::Dwarf32,
4379
            version: 4,
4380
            augmentation: None,
4381
            address_size: 4,
4382
            code_alignment_factor: 16,
4383
            data_alignment_factor: 32,
4384
            return_address_register: Register(1),
4385
            initial_instructions: EndianSlice::new(&[], BigEndian),
4386
        };
4387
4388
        let mut fde = FrameDescriptionEntry {
4389
            offset: 0,
4390
            length: 0,
4391
            format: Format::Dwarf32,
4392
            cie: cie.clone(),
4393
            initial_address: 0xfeed_beef,
4394
            address_range: 39,
4395
            augmentation: None,
4396
            instructions: EndianSlice::new(&expected_instrs, BigEndian),
4397
        };
4398
4399
        let kind = debug_frame_be();
4400
        let section = Section::with_endian(kind.endian())
4401
            .fde(kind, cie_offset, &mut fde)
4402
            .append_bytes(&expected_rest);
4403
4404
        let section = section.get_contents().unwrap();
4405
        let debug_frame = kind.section(&section);
4406
        let rest = &mut EndianSlice::new(&section, BigEndian);
4407
4408
        let bases = Default::default();
4409
        match parse_cfi_entry(&bases, &debug_frame, rest) {
4410
            Ok(Some(CieOrFde::Fde(partial))) => {
4411
                assert_eq!(*rest, EndianSlice::new(&expected_rest, BigEndian));
4412
4413
                assert_eq!(partial.length, fde.length);
4414
                assert_eq!(partial.format, fde.format);
4415
                assert_eq!(partial.cie_offset, DebugFrameOffset(cie_offset as usize));
4416
4417
                let get_cie = |_: &_, _: &_, offset| {
4418
                    assert_eq!(offset, DebugFrameOffset(cie_offset as usize));
4419
                    Ok(cie.clone())
4420
                };
4421
4422
                assert_eq!(partial.parse(get_cie), Ok(fde));
4423
            }
4424
            otherwise => panic!("Unexpected result: {:#?}", otherwise),
4425
        }
4426
    }
4427
4428
    #[test]
4429
    fn test_cfi_entries_iter() {
4430
        let expected_instrs1: Vec<_> = (0..4).map(|_| constants::DW_CFA_nop.0).collect();
4431
4432
        let expected_instrs2: Vec<_> = (0..8).map(|_| constants::DW_CFA_nop.0).collect();
4433
4434
        let expected_instrs3: Vec<_> = (0..12).map(|_| constants::DW_CFA_nop.0).collect();
4435
4436
        let expected_instrs4: Vec<_> = (0..16).map(|_| constants::DW_CFA_nop.0).collect();
4437
4438
        let mut cie1 = CommonInformationEntry {
4439
            offset: 0,
4440
            length: 0,
4441
            format: Format::Dwarf32,
4442
            version: 4,
4443
            augmentation: None,
4444
            address_size: 4,
4445
            code_alignment_factor: 1,
4446
            data_alignment_factor: 2,
4447
            return_address_register: Register(3),
4448
            initial_instructions: EndianSlice::new(&expected_instrs1, BigEndian),
4449
        };
4450
4451
        let mut cie2 = CommonInformationEntry {
4452
            offset: 0,
4453
            length: 0,
4454
            format: Format::Dwarf32,
4455
            version: 4,
4456
            augmentation: None,
4457
            address_size: 4,
4458
            code_alignment_factor: 3,
4459
            data_alignment_factor: 2,
4460
            return_address_register: Register(1),
4461
            initial_instructions: EndianSlice::new(&expected_instrs2, BigEndian),
4462
        };
4463
4464
        let cie1_location = Label::new();
4465
        let cie2_location = Label::new();
4466
4467
        // Write the CIEs first so that their length gets set before we clone
4468
        // them into the FDEs and our equality assertions down the line end up
4469
        // with all the CIEs always having he correct length.
4470
        let kind = debug_frame_be();
4471
        let section = Section::with_endian(kind.endian())
4472
            .mark(&cie1_location)
4473
            .cie(kind, None, &mut cie1)
4474
            .mark(&cie2_location)
4475
            .cie(kind, None, &mut cie2);
4476
4477
        let mut fde1 = FrameDescriptionEntry {
4478
            offset: 0,
4479
            length: 0,
4480
            format: Format::Dwarf32,
4481
            cie: cie1.clone(),
4482
            initial_address: 0xfeed_beef,
4483
            address_range: 39,
4484
            augmentation: None,
4485
            instructions: EndianSlice::new(&expected_instrs3, BigEndian),
4486
        };
4487
4488
        let mut fde2 = FrameDescriptionEntry {
4489
            offset: 0,
4490
            length: 0,
4491
            format: Format::Dwarf32,
4492
            cie: cie2.clone(),
4493
            initial_address: 0xfeed_face,
4494
            address_range: 9000,
4495
            augmentation: None,
4496
            instructions: EndianSlice::new(&expected_instrs4, BigEndian),
4497
        };
4498
4499
        let section =
4500
            section
4501
                .fde(kind, &cie1_location, &mut fde1)
4502
                .fde(kind, &cie2_location, &mut fde2);
4503
4504
        section.start().set_const(0);
4505
4506
        let cie1_offset = cie1_location.value().unwrap() as usize;
4507
        let cie2_offset = cie2_location.value().unwrap() as usize;
4508
4509
        let contents = section.get_contents().unwrap();
4510
        let debug_frame = kind.section(&contents);
4511
4512
        let bases = Default::default();
4513
        let mut entries = debug_frame.entries(&bases);
4514
4515
        assert_eq!(entries.next(), Ok(Some(CieOrFde::Cie(cie1.clone()))));
4516
        assert_eq!(entries.next(), Ok(Some(CieOrFde::Cie(cie2.clone()))));
4517
4518
        match entries.next() {
4519
            Ok(Some(CieOrFde::Fde(partial))) => {
4520
                assert_eq!(partial.length, fde1.length);
4521
                assert_eq!(partial.format, fde1.format);
4522
                assert_eq!(partial.cie_offset, DebugFrameOffset(cie1_offset));
4523
4524
                let get_cie = |_: &_, _: &_, offset| {
4525
                    assert_eq!(offset, DebugFrameOffset(cie1_offset));
4526
                    Ok(cie1.clone())
4527
                };
4528
                assert_eq!(partial.parse(get_cie), Ok(fde1));
4529
            }
4530
            otherwise => panic!("Unexpected result: {:#?}", otherwise),
4531
        }
4532
4533
        match entries.next() {
4534
            Ok(Some(CieOrFde::Fde(partial))) => {
4535
                assert_eq!(partial.length, fde2.length);
4536
                assert_eq!(partial.format, fde2.format);
4537
                assert_eq!(partial.cie_offset, DebugFrameOffset(cie2_offset));
4538
4539
                let get_cie = |_: &_, _: &_, offset| {
4540
                    assert_eq!(offset, DebugFrameOffset(cie2_offset));
4541
                    Ok(cie2.clone())
4542
                };
4543
                assert_eq!(partial.parse(get_cie), Ok(fde2));
4544
            }
4545
            otherwise => panic!("Unexpected result: {:#?}", otherwise),
4546
        }
4547
4548
        assert_eq!(entries.next(), Ok(None));
4549
    }
4550
4551
    #[test]
4552
    fn test_parse_cie_from_offset() {
4553
        let filler = [1, 2, 3, 4, 5, 6, 7, 8, 9];
4554
        let instrs: Vec<_> = (0..5).map(|_| constants::DW_CFA_nop.0).collect();
4555
4556
        let mut cie = CommonInformationEntry {
4557
            offset: 0,
4558
            length: 0,
4559
            format: Format::Dwarf64,
4560
            version: 4,
4561
            augmentation: None,
4562
            address_size: 4,
4563
            code_alignment_factor: 4,
4564
            data_alignment_factor: 8,
4565
            return_address_register: Register(12),
4566
            initial_instructions: EndianSlice::new(&instrs, LittleEndian),
4567
        };
4568
4569
        let cie_location = Label::new();
4570
4571
        let kind = debug_frame_le();
4572
        let section = Section::with_endian(kind.endian())
4573
            .append_bytes(&filler)
4574
            .mark(&cie_location)
4575
            .cie(kind, None, &mut cie)
4576
            .append_bytes(&filler);
4577
4578
        section.start().set_const(0);
4579
4580
        let cie_offset = DebugFrameOffset(cie_location.value().unwrap() as usize);
4581
4582
        let contents = section.get_contents().unwrap();
4583
        let debug_frame = kind.section(&contents);
4584
        let bases = Default::default();
4585
4586
        assert_eq!(debug_frame.cie_from_offset(&bases, cie_offset), Ok(cie));
4587
    }
4588
4589
    fn parse_cfi_instruction<R: Reader + Default>(
4590
        input: &mut R,
4591
        address_size: u8,
4592
    ) -> Result<CallFrameInstruction<R::Offset>> {
4593
        let section = input.clone();
4594
        let parameters = &PointerEncodingParameters {
4595
            bases: &SectionBaseAddresses::default(),
4596
            func_base: None,
4597
            address_size,
4598
            section: &section,
4599
        };
4600
        CallFrameInstruction::parse(input, None, parameters, Vendor::Default)
4601
    }
4602
4603
    #[test]
4604
    fn test_parse_cfi_instruction_advance_loc() {
4605
        let expected_rest = [1, 2, 3, 4];
4606
        let expected_delta = 42;
4607
        let section = Section::with_endian(Endian::Little)
4608
            .D8(constants::DW_CFA_advance_loc.0 | expected_delta)
4609
            .append_bytes(&expected_rest);
4610
        let contents = section.get_contents().unwrap();
4611
        let input = &mut EndianSlice::new(&contents, LittleEndian);
4612
        assert_eq!(
4613
            parse_cfi_instruction(input, 8),
4614
            Ok(CallFrameInstruction::AdvanceLoc {
4615
                delta: u32::from(expected_delta),
4616
            })
4617
        );
4618
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4619
    }
4620
4621
    #[test]
4622
    fn test_parse_cfi_instruction_offset() {
4623
        let expected_rest = [1, 2, 3, 4];
4624
        let expected_reg = 3;
4625
        let expected_offset = 1997;
4626
        let section = Section::with_endian(Endian::Little)
4627
            .D8(constants::DW_CFA_offset.0 | expected_reg)
4628
            .uleb(expected_offset)
4629
            .append_bytes(&expected_rest);
4630
        let contents = section.get_contents().unwrap();
4631
        let input = &mut EndianSlice::new(&contents, LittleEndian);
4632
        assert_eq!(
4633
            parse_cfi_instruction(input, 8),
4634
            Ok(CallFrameInstruction::Offset {
4635
                register: Register(expected_reg.into()),
4636
                factored_offset: expected_offset,
4637
            })
4638
        );
4639
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4640
    }
4641
4642
    #[test]
4643
    fn test_parse_cfi_instruction_restore() {
4644
        let expected_rest = [1, 2, 3, 4];
4645
        let expected_reg = 3;
4646
        let section = Section::with_endian(Endian::Little)
4647
            .D8(constants::DW_CFA_restore.0 | expected_reg)
4648
            .append_bytes(&expected_rest);
4649
        let contents = section.get_contents().unwrap();
4650
        let input = &mut EndianSlice::new(&contents, LittleEndian);
4651
        assert_eq!(
4652
            parse_cfi_instruction(input, 8),
4653
            Ok(CallFrameInstruction::Restore {
4654
                register: Register(expected_reg.into()),
4655
            })
4656
        );
4657
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4658
    }
4659
4660
    #[test]
4661
    fn test_parse_cfi_instruction_nop() {
4662
        let expected_rest = [1, 2, 3, 4];
4663
        let section = Section::with_endian(Endian::Little)
4664
            .D8(constants::DW_CFA_nop.0)
4665
            .append_bytes(&expected_rest);
4666
        let contents = section.get_contents().unwrap();
4667
        let input = &mut EndianSlice::new(&contents, LittleEndian);
4668
        assert_eq!(
4669
            parse_cfi_instruction(input, 8),
4670
            Ok(CallFrameInstruction::Nop)
4671
        );
4672
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4673
    }
4674
4675
    #[test]
4676
    fn test_parse_cfi_instruction_set_loc() {
4677
        let expected_rest = [1, 2, 3, 4];
4678
        let expected_addr = 0xdead_beef;
4679
        let section = Section::with_endian(Endian::Little)
4680
            .D8(constants::DW_CFA_set_loc.0)
4681
            .L64(expected_addr)
4682
            .append_bytes(&expected_rest);
4683
        let contents = section.get_contents().unwrap();
4684
        let input = &mut EndianSlice::new(&contents, LittleEndian);
4685
        assert_eq!(
4686
            parse_cfi_instruction(input, 8),
4687
            Ok(CallFrameInstruction::SetLoc {
4688
                address: expected_addr,
4689
            })
4690
        );
4691
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4692
    }
4693
4694
    #[test]
4695
    fn test_parse_cfi_instruction_set_loc_encoding() {
4696
        let text_base = 0xfeed_face;
4697
        let addr_offset = 0xbeef;
4698
        let expected_addr = text_base + addr_offset;
4699
        let expected_rest = [1, 2, 3, 4];
4700
        let section = Section::with_endian(Endian::Little)
4701
            .D8(constants::DW_CFA_set_loc.0)
4702
            .L64(addr_offset)
4703
            .append_bytes(&expected_rest);
4704
        let contents = section.get_contents().unwrap();
4705
        let input = &mut EndianSlice::new(&contents, LittleEndian);
4706
        let parameters = &PointerEncodingParameters {
4707
            bases: &BaseAddresses::default().set_text(text_base).eh_frame,
4708
            func_base: None,
4709
            address_size: 8,
4710
            section: &EndianSlice::new(&[], LittleEndian),
4711
        };
4712
        assert_eq!(
4713
            CallFrameInstruction::parse(
4714
                input,
4715
                Some(constants::DW_EH_PE_textrel),
4716
                parameters,
4717
                Vendor::Default
4718
            ),
4719
            Ok(CallFrameInstruction::SetLoc {
4720
                address: expected_addr,
4721
            })
4722
        );
4723
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4724
    }
4725
4726
    #[test]
4727
    fn test_parse_cfi_instruction_advance_loc1() {
4728
        let expected_rest = [1, 2, 3, 4];
4729
        let expected_delta = 8;
4730
        let section = Section::with_endian(Endian::Little)
4731
            .D8(constants::DW_CFA_advance_loc1.0)
4732
            .D8(expected_delta)
4733
            .append_bytes(&expected_rest);
4734
        let contents = section.get_contents().unwrap();
4735
        let input = &mut EndianSlice::new(&contents, LittleEndian);
4736
        assert_eq!(
4737
            parse_cfi_instruction(input, 8),
4738
            Ok(CallFrameInstruction::AdvanceLoc {
4739
                delta: u32::from(expected_delta),
4740
            })
4741
        );
4742
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4743
    }
4744
4745
    #[test]
4746
    fn test_parse_cfi_instruction_advance_loc2() {
4747
        let expected_rest = [1, 2, 3, 4];
4748
        let expected_delta = 500;
4749
        let section = Section::with_endian(Endian::Little)
4750
            .D8(constants::DW_CFA_advance_loc2.0)
4751
            .L16(expected_delta)
4752
            .append_bytes(&expected_rest);
4753
        let contents = section.get_contents().unwrap();
4754
        let input = &mut EndianSlice::new(&contents, LittleEndian);
4755
        assert_eq!(
4756
            parse_cfi_instruction(input, 8),
4757
            Ok(CallFrameInstruction::AdvanceLoc {
4758
                delta: u32::from(expected_delta),
4759
            })
4760
        );
4761
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4762
    }
4763
4764
    #[test]
4765
    fn test_parse_cfi_instruction_advance_loc4() {
4766
        let expected_rest = [1, 2, 3, 4];
4767
        let expected_delta = 1 << 20;
4768
        let section = Section::with_endian(Endian::Little)
4769
            .D8(constants::DW_CFA_advance_loc4.0)
4770
            .L32(expected_delta)
4771
            .append_bytes(&expected_rest);
4772
        let contents = section.get_contents().unwrap();
4773
        let input = &mut EndianSlice::new(&contents, LittleEndian);
4774
        assert_eq!(
4775
            parse_cfi_instruction(input, 8),
4776
            Ok(CallFrameInstruction::AdvanceLoc {
4777
                delta: expected_delta,
4778
            })
4779
        );
4780
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4781
    }
4782
4783
    #[test]
4784
    fn test_parse_cfi_instruction_offset_extended() {
4785
        let expected_rest = [1, 2, 3, 4];
4786
        let expected_reg = 7;
4787
        let expected_offset = 33;
4788
        let section = Section::with_endian(Endian::Little)
4789
            .D8(constants::DW_CFA_offset_extended.0)
4790
            .uleb(expected_reg.into())
4791
            .uleb(expected_offset)
4792
            .append_bytes(&expected_rest);
4793
        let contents = section.get_contents().unwrap();
4794
        let input = &mut EndianSlice::new(&contents, LittleEndian);
4795
        assert_eq!(
4796
            parse_cfi_instruction(input, 8),
4797
            Ok(CallFrameInstruction::Offset {
4798
                register: Register(expected_reg),
4799
                factored_offset: expected_offset,
4800
            })
4801
        );
4802
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4803
    }
4804
4805
    #[test]
4806
    fn test_parse_cfi_instruction_restore_extended() {
4807
        let expected_rest = [1, 2, 3, 4];
4808
        let expected_reg = 7;
4809
        let section = Section::with_endian(Endian::Little)
4810
            .D8(constants::DW_CFA_restore_extended.0)
4811
            .uleb(expected_reg.into())
4812
            .append_bytes(&expected_rest);
4813
        let contents = section.get_contents().unwrap();
4814
        let input = &mut EndianSlice::new(&contents, LittleEndian);
4815
        assert_eq!(
4816
            parse_cfi_instruction(input, 8),
4817
            Ok(CallFrameInstruction::Restore {
4818
                register: Register(expected_reg),
4819
            })
4820
        );
4821
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4822
    }
4823
4824
    #[test]
4825
    fn test_parse_cfi_instruction_undefined() {
4826
        let expected_rest = [1, 2, 3, 4];
4827
        let expected_reg = 7;
4828
        let section = Section::with_endian(Endian::Little)
4829
            .D8(constants::DW_CFA_undefined.0)
4830
            .uleb(expected_reg.into())
4831
            .append_bytes(&expected_rest);
4832
        let contents = section.get_contents().unwrap();
4833
        let input = &mut EndianSlice::new(&contents, LittleEndian);
4834
        assert_eq!(
4835
            parse_cfi_instruction(input, 8),
4836
            Ok(CallFrameInstruction::Undefined {
4837
                register: Register(expected_reg),
4838
            })
4839
        );
4840
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4841
    }
4842
4843
    #[test]
4844
    fn test_parse_cfi_instruction_same_value() {
4845
        let expected_rest = [1, 2, 3, 4];
4846
        let expected_reg = 7;
4847
        let section = Section::with_endian(Endian::Little)
4848
            .D8(constants::DW_CFA_same_value.0)
4849
            .uleb(expected_reg.into())
4850
            .append_bytes(&expected_rest);
4851
        let contents = section.get_contents().unwrap();
4852
        let input = &mut EndianSlice::new(&contents, LittleEndian);
4853
        assert_eq!(
4854
            parse_cfi_instruction(input, 8),
4855
            Ok(CallFrameInstruction::SameValue {
4856
                register: Register(expected_reg),
4857
            })
4858
        );
4859
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4860
    }
4861
4862
    #[test]
4863
    fn test_parse_cfi_instruction_register() {
4864
        let expected_rest = [1, 2, 3, 4];
4865
        let expected_dest_reg = 7;
4866
        let expected_src_reg = 8;
4867
        let section = Section::with_endian(Endian::Little)
4868
            .D8(constants::DW_CFA_register.0)
4869
            .uleb(expected_dest_reg.into())
4870
            .uleb(expected_src_reg.into())
4871
            .append_bytes(&expected_rest);
4872
        let contents = section.get_contents().unwrap();
4873
        let input = &mut EndianSlice::new(&contents, LittleEndian);
4874
        assert_eq!(
4875
            parse_cfi_instruction(input, 8),
4876
            Ok(CallFrameInstruction::Register {
4877
                dest_register: Register(expected_dest_reg),
4878
                src_register: Register(expected_src_reg),
4879
            })
4880
        );
4881
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4882
    }
4883
4884
    #[test]
4885
    fn test_parse_cfi_instruction_remember_state() {
4886
        let expected_rest = [1, 2, 3, 4];
4887
        let section = Section::with_endian(Endian::Little)
4888
            .D8(constants::DW_CFA_remember_state.0)
4889
            .append_bytes(&expected_rest);
4890
        let contents = section.get_contents().unwrap();
4891
        let input = &mut EndianSlice::new(&contents, LittleEndian);
4892
        assert_eq!(
4893
            parse_cfi_instruction(input, 8),
4894
            Ok(CallFrameInstruction::RememberState)
4895
        );
4896
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4897
    }
4898
4899
    #[test]
4900
    fn test_parse_cfi_instruction_restore_state() {
4901
        let expected_rest = [1, 2, 3, 4];
4902
        let section = Section::with_endian(Endian::Little)
4903
            .D8(constants::DW_CFA_restore_state.0)
4904
            .append_bytes(&expected_rest);
4905
        let contents = section.get_contents().unwrap();
4906
        let input = &mut EndianSlice::new(&contents, LittleEndian);
4907
        assert_eq!(
4908
            parse_cfi_instruction(input, 8),
4909
            Ok(CallFrameInstruction::RestoreState)
4910
        );
4911
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4912
    }
4913
4914
    #[test]
4915
    fn test_parse_cfi_instruction_def_cfa() {
4916
        let expected_rest = [1, 2, 3, 4];
4917
        let expected_reg = 2;
4918
        let expected_offset = 0;
4919
        let section = Section::with_endian(Endian::Little)
4920
            .D8(constants::DW_CFA_def_cfa.0)
4921
            .uleb(expected_reg.into())
4922
            .uleb(expected_offset)
4923
            .append_bytes(&expected_rest);
4924
        let contents = section.get_contents().unwrap();
4925
        let input = &mut EndianSlice::new(&contents, LittleEndian);
4926
        assert_eq!(
4927
            parse_cfi_instruction(input, 8),
4928
            Ok(CallFrameInstruction::DefCfa {
4929
                register: Register(expected_reg),
4930
                offset: expected_offset,
4931
            })
4932
        );
4933
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4934
    }
4935
4936
    #[test]
4937
    fn test_parse_cfi_instruction_def_cfa_register() {
4938
        let expected_rest = [1, 2, 3, 4];
4939
        let expected_reg = 2;
4940
        let section = Section::with_endian(Endian::Little)
4941
            .D8(constants::DW_CFA_def_cfa_register.0)
4942
            .uleb(expected_reg.into())
4943
            .append_bytes(&expected_rest);
4944
        let contents = section.get_contents().unwrap();
4945
        let input = &mut EndianSlice::new(&contents, LittleEndian);
4946
        assert_eq!(
4947
            parse_cfi_instruction(input, 8),
4948
            Ok(CallFrameInstruction::DefCfaRegister {
4949
                register: Register(expected_reg),
4950
            })
4951
        );
4952
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4953
    }
4954
4955
    #[test]
4956
    fn test_parse_cfi_instruction_def_cfa_offset() {
4957
        let expected_rest = [1, 2, 3, 4];
4958
        let expected_offset = 23;
4959
        let section = Section::with_endian(Endian::Little)
4960
            .D8(constants::DW_CFA_def_cfa_offset.0)
4961
            .uleb(expected_offset)
4962
            .append_bytes(&expected_rest);
4963
        let contents = section.get_contents().unwrap();
4964
        let input = &mut EndianSlice::new(&contents, LittleEndian);
4965
        assert_eq!(
4966
            parse_cfi_instruction(input, 8),
4967
            Ok(CallFrameInstruction::DefCfaOffset {
4968
                offset: expected_offset,
4969
            })
4970
        );
4971
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4972
    }
4973
4974
    #[test]
4975
    fn test_parse_cfi_instruction_def_cfa_expression() {
4976
        let expected_rest = [1, 2, 3, 4];
4977
        let expected_expr = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
4978
4979
        let length = Label::new();
4980
        let start = Label::new();
4981
        let end = Label::new();
4982
4983
        let section = Section::with_endian(Endian::Little)
4984
            .D8(constants::DW_CFA_def_cfa_expression.0)
4985
            .D8(&length)
4986
            .mark(&start)
4987
            .append_bytes(&expected_expr)
4988
            .mark(&end)
4989
            .append_bytes(&expected_rest);
4990
4991
        length.set_const((&end - &start) as u64);
4992
        let expected_expression = UnwindExpression {
4993
            offset: (&start - &section.start()) as usize,
4994
            length: (&end - &start) as usize,
4995
        };
4996
        let contents = section.get_contents().unwrap();
4997
        let input = &mut EndianSlice::new(&contents, LittleEndian);
4998
4999
        assert_eq!(
5000
            parse_cfi_instruction(input, 8),
5001
            Ok(CallFrameInstruction::DefCfaExpression {
5002
                expression: expected_expression,
5003
            })
5004
        );
5005
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
5006
    }
5007
5008
    #[test]
5009
    fn test_parse_cfi_instruction_expression() {
5010
        let expected_rest = [1, 2, 3, 4];
5011
        let expected_reg = 99;
5012
        let expected_expr = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
5013
5014
        let length = Label::new();
5015
        let start = Label::new();
5016
        let end = Label::new();
5017
5018
        let section = Section::with_endian(Endian::Little)
5019
            .D8(constants::DW_CFA_expression.0)
5020
            .uleb(expected_reg.into())
5021
            .D8(&length)
5022
            .mark(&start)
5023
            .append_bytes(&expected_expr)
5024
            .mark(&end)
5025
            .append_bytes(&expected_rest);
5026
5027
        length.set_const((&end - &start) as u64);
5028
        let expected_expression = UnwindExpression {
5029
            offset: (&start - &section.start()) as usize,
5030
            length: (&end - &start) as usize,
5031
        };
5032
        let contents = section.get_contents().unwrap();
5033
        let input = &mut EndianSlice::new(&contents, LittleEndian);
5034
5035
        assert_eq!(
5036
            parse_cfi_instruction(input, 8),
5037
            Ok(CallFrameInstruction::Expression {
5038
                register: Register(expected_reg),
5039
                expression: expected_expression,
5040
            })
5041
        );
5042
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
5043
    }
5044
5045
    #[test]
5046
    fn test_parse_cfi_instruction_offset_extended_sf() {
5047
        let expected_rest = [1, 2, 3, 4];
5048
        let expected_reg = 7;
5049
        let expected_offset = -33;
5050
        let section = Section::with_endian(Endian::Little)
5051
            .D8(constants::DW_CFA_offset_extended_sf.0)
5052
            .uleb(expected_reg.into())
5053
            .sleb(expected_offset)
5054
            .append_bytes(&expected_rest);
5055
        let contents = section.get_contents().unwrap();
5056
        let input = &mut EndianSlice::new(&contents, LittleEndian);
5057
        assert_eq!(
5058
            parse_cfi_instruction(input, 8),
5059
            Ok(CallFrameInstruction::OffsetExtendedSf {
5060
                register: Register(expected_reg),
5061
                factored_offset: expected_offset,
5062
            })
5063
        );
5064
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
5065
    }
5066
5067
    #[test]
5068
    fn test_parse_cfi_instruction_def_cfa_sf() {
5069
        let expected_rest = [1, 2, 3, 4];
5070
        let expected_reg = 2;
5071
        let expected_offset = -9999;
5072
        let section = Section::with_endian(Endian::Little)
5073
            .D8(constants::DW_CFA_def_cfa_sf.0)
5074
            .uleb(expected_reg.into())
5075
            .sleb(expected_offset)
5076
            .append_bytes(&expected_rest);
5077
        let contents = section.get_contents().unwrap();
5078
        let input = &mut EndianSlice::new(&contents, LittleEndian);
5079
        assert_eq!(
5080
            parse_cfi_instruction(input, 8),
5081
            Ok(CallFrameInstruction::DefCfaSf {
5082
                register: Register(expected_reg),
5083
                factored_offset: expected_offset,
5084
            })
5085
        );
5086
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
5087
    }
5088
5089
    #[test]
5090
    fn test_parse_cfi_instruction_def_cfa_offset_sf() {
5091
        let expected_rest = [1, 2, 3, 4];
5092
        let expected_offset = -123;
5093
        let section = Section::with_endian(Endian::Little)
5094
            .D8(constants::DW_CFA_def_cfa_offset_sf.0)
5095
            .sleb(expected_offset)
5096
            .append_bytes(&expected_rest);
5097
        let contents = section.get_contents().unwrap();
5098
        let input = &mut EndianSlice::new(&contents, LittleEndian);
5099
        assert_eq!(
5100
            parse_cfi_instruction(input, 8),
5101
            Ok(CallFrameInstruction::DefCfaOffsetSf {
5102
                factored_offset: expected_offset,
5103
            })
5104
        );
5105
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
5106
    }
5107
5108
    #[test]
5109
    fn test_parse_cfi_instruction_val_offset() {
5110
        let expected_rest = [1, 2, 3, 4];
5111
        let expected_reg = 50;
5112
        let expected_offset = 23;
5113
        let section = Section::with_endian(Endian::Little)
5114
            .D8(constants::DW_CFA_val_offset.0)
5115
            .uleb(expected_reg.into())
5116
            .uleb(expected_offset)
5117
            .append_bytes(&expected_rest);
5118
        let contents = section.get_contents().unwrap();
5119
        let input = &mut EndianSlice::new(&contents, LittleEndian);
5120
        assert_eq!(
5121
            parse_cfi_instruction(input, 8),
5122
            Ok(CallFrameInstruction::ValOffset {
5123
                register: Register(expected_reg),
5124
                factored_offset: expected_offset,
5125
            })
5126
        );
5127
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
5128
    }
5129
5130
    #[test]
5131
    fn test_parse_cfi_instruction_val_offset_sf() {
5132
        let expected_rest = [1, 2, 3, 4];
5133
        let expected_reg = 50;
5134
        let expected_offset = -23;
5135
        let section = Section::with_endian(Endian::Little)
5136
            .D8(constants::DW_CFA_val_offset_sf.0)
5137
            .uleb(expected_reg.into())
5138
            .sleb(expected_offset)
5139
            .append_bytes(&expected_rest);
5140
        let contents = section.get_contents().unwrap();
5141
        let input = &mut EndianSlice::new(&contents, LittleEndian);
5142
        assert_eq!(
5143
            parse_cfi_instruction(input, 8),
5144
            Ok(CallFrameInstruction::ValOffsetSf {
5145
                register: Register(expected_reg),
5146
                factored_offset: expected_offset,
5147
            })
5148
        );
5149
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
5150
    }
5151
5152
    #[test]
5153
    fn test_parse_cfi_instruction_val_expression() {
5154
        let expected_rest = [1, 2, 3, 4];
5155
        let expected_reg = 50;
5156
        let expected_expr = [2, 2, 1, 1, 5, 5];
5157
5158
        let length = Label::new();
5159
        let start = Label::new();
5160
        let end = Label::new();
5161
5162
        let section = Section::with_endian(Endian::Little)
5163
            .D8(constants::DW_CFA_val_expression.0)
5164
            .uleb(expected_reg.into())
5165
            .D8(&length)
5166
            .mark(&start)
5167
            .append_bytes(&expected_expr)
5168
            .mark(&end)
5169
            .append_bytes(&expected_rest);
5170
5171
        length.set_const((&end - &start) as u64);
5172
        let expected_expression = UnwindExpression {
5173
            offset: (&start - &section.start()) as usize,
5174
            length: (&end - &start) as usize,
5175
        };
5176
        let contents = section.get_contents().unwrap();
5177
        let input = &mut EndianSlice::new(&contents, LittleEndian);
5178
5179
        assert_eq!(
5180
            parse_cfi_instruction(input, 8),
5181
            Ok(CallFrameInstruction::ValExpression {
5182
                register: Register(expected_reg),
5183
                expression: expected_expression,
5184
            })
5185
        );
5186
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
5187
    }
5188
5189
    #[test]
5190
    fn test_parse_cfi_instruction_negate_ra_state() {
5191
        let expected_rest = [1, 2, 3, 4];
5192
        let section = Section::with_endian(Endian::Little)
5193
            .D8(constants::DW_CFA_AARCH64_negate_ra_state.0)
5194
            .append_bytes(&expected_rest);
5195
        let contents = section.get_contents().unwrap();
5196
        let input = &mut EndianSlice::new(&contents, LittleEndian);
5197
        let parameters = &PointerEncodingParameters {
5198
            bases: &SectionBaseAddresses::default(),
5199
            func_base: None,
5200
            address_size: 8,
5201
            section: &EndianSlice::default(),
5202
        };
5203
        assert_eq!(
5204
            CallFrameInstruction::parse(input, None, parameters, Vendor::AArch64),
5205
            Ok(CallFrameInstruction::NegateRaState)
5206
        );
5207
        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
5208
    }
5209
5210
    #[test]
5211
    fn test_parse_cfi_instruction_unknown_instruction() {
5212
        let expected_rest = [1, 2, 3, 4];
5213
        let unknown_instr = constants::DwCfa(0b0011_1111);
5214
        let section = Section::with_endian(Endian::Little)
5215
            .D8(unknown_instr.0)
5216
            .append_bytes(&expected_rest);
5217
        let contents = section.get_contents().unwrap();
5218
        let input = &mut EndianSlice::new(&contents, LittleEndian);
5219
        assert_eq!(
5220
            parse_cfi_instruction(input, 8),
5221
            Err(Error::UnknownCallFrameInstruction(unknown_instr))
5222
        );
5223
    }
5224
5225
    #[test]
5226
    fn test_call_frame_instruction_iter_ok() {
5227
        let expected_reg = 50;
5228
        let expected_expr = [2, 2, 1, 1, 5, 5];
5229
        let expected_delta = 230;
5230
5231
        let length = Label::new();
5232
        let start = Label::new();
5233
        let end = Label::new();
5234
5235
        let section = Section::with_endian(Endian::Big)
5236
            .D8(constants::DW_CFA_val_expression.0)
5237
            .uleb(expected_reg.into())
5238
            .D8(&length)
5239
            .mark(&start)
5240
            .append_bytes(&expected_expr)
5241
            .mark(&end)
5242
            .D8(constants::DW_CFA_advance_loc1.0)
5243
            .D8(expected_delta);
5244
5245
        length.set_const((&end - &start) as u64);
5246
        let expected_expression = UnwindExpression {
5247
            offset: (&start - &section.start()) as usize,
5248
            length: (&end - &start) as usize,
5249
        };
5250
        let contents = section.get_contents().unwrap();
5251
        let input = EndianSlice::new(&contents, BigEndian);
5252
        let parameters = PointerEncodingParameters {
5253
            bases: &SectionBaseAddresses::default(),
5254
            func_base: None,
5255
            address_size: 8,
5256
            section: &input,
5257
        };
5258
        let mut iter = CallFrameInstructionIter {
5259
            input,
5260
            address_encoding: None,
5261
            parameters,
5262
            vendor: Vendor::Default,
5263
        };
5264
5265
        assert_eq!(
5266
            iter.next(),
5267
            Ok(Some(CallFrameInstruction::ValExpression {
5268
                register: Register(expected_reg),
5269
                expression: expected_expression,
5270
            }))
5271
        );
5272
5273
        assert_eq!(
5274
            iter.next(),
5275
            Ok(Some(CallFrameInstruction::AdvanceLoc {
5276
                delta: u32::from(expected_delta),
5277
            }))
5278
        );
5279
5280
        assert_eq!(iter.next(), Ok(None));
5281
    }
5282
5283
    #[test]
5284
    fn test_call_frame_instruction_iter_err() {
5285
        // DW_CFA_advance_loc1 without an operand.
5286
        let section = Section::with_endian(Endian::Big).D8(constants::DW_CFA_advance_loc1.0);
5287
5288
        let contents = section.get_contents().unwrap();
5289
        let input = EndianSlice::new(&contents, BigEndian);
5290
        let parameters = PointerEncodingParameters {
5291
            bases: &SectionBaseAddresses::default(),
5292
            func_base: None,
5293
            address_size: 8,
5294
            section: &EndianSlice::default(),
5295
        };
5296
        let mut iter = CallFrameInstructionIter {
5297
            input,
5298
            address_encoding: None,
5299
            parameters,
5300
            vendor: Vendor::Default,
5301
        };
5302
5303
        assert_eq!(
5304
            iter.next().map_eof(&contents),
5305
            Err(Error::UnexpectedEof(ReaderOffsetId(1)))
5306
        );
5307
        assert_eq!(iter.next(), Ok(None));
5308
    }
5309
5310
    fn assert_eval<'a, I>(
5311
        mut initial_ctx: UnwindContext<usize>,
5312
        expected_ctx: UnwindContext<usize>,
5313
        cie: CommonInformationEntry<EndianSlice<'a, LittleEndian>>,
5314
        fde: Option<FrameDescriptionEntry<EndianSlice<'a, LittleEndian>>>,
5315
        instructions: I,
5316
    ) where
5317
        I: AsRef<[(Result<bool>, CallFrameInstruction<usize>)]>,
5318
    {
5319
        {
5320
            let section = &DebugFrame::from(EndianSlice::default());
5321
            let bases = &BaseAddresses::default();
5322
            let mut table = match fde {
5323
                Some(fde) => UnwindTable::new_for_fde(section, bases, &mut initial_ctx, &fde),
5324
                None => UnwindTable::new_for_cie(section, bases, &mut initial_ctx, &cie),
5325
            };
5326
            for (expected_result, instruction) in instructions.as_ref() {
5327
                assert_eq!(*expected_result, table.evaluate(instruction.clone()));
5328
            }
5329
        }
5330
5331
        assert_eq!(expected_ctx, initial_ctx);
5332
    }
5333
5334
    fn make_test_cie<'a>() -> CommonInformationEntry<EndianSlice<'a, LittleEndian>> {
5335
        CommonInformationEntry {
5336
            offset: 0,
5337
            format: Format::Dwarf64,
5338
            length: 0,
5339
            return_address_register: Register(0),
5340
            version: 4,
5341
            address_size: mem::size_of::<usize>() as u8,
5342
            initial_instructions: EndianSlice::new(&[], LittleEndian),
5343
            augmentation: None,
5344
            data_alignment_factor: 2,
5345
            code_alignment_factor: 3,
5346
        }
5347
    }
5348
5349
    #[test]
5350
    fn test_eval_set_loc() {
5351
        let cie = make_test_cie();
5352
        let ctx = UnwindContext::new();
5353
        let mut expected = ctx.clone();
5354
        expected.row_mut().end_address = 42;
5355
        let instructions = [(Ok(true), CallFrameInstruction::SetLoc { address: 42 })];
5356
        assert_eval(ctx, expected, cie, None, instructions);
5357
    }
5358
5359
    #[test]
5360
    fn test_eval_set_loc_backwards() {
5361
        let cie = make_test_cie();
5362
        let mut ctx = UnwindContext::new();
5363
        ctx.row_mut().start_address = 999;
5364
        let expected = ctx.clone();
5365
        let instructions = [(
5366
            Err(Error::InvalidAddressRange),
5367
            CallFrameInstruction::SetLoc { address: 42 },
5368
        )];
5369
        assert_eval(ctx, expected, cie, None, instructions);
5370
    }
5371
5372
    #[test]
5373
    fn test_eval_advance_loc() {
5374
        let cie = make_test_cie();
5375
        let mut ctx = UnwindContext::new();
5376
        ctx.row_mut().start_address = 3;
5377
        let mut expected = ctx.clone();
5378
        expected.row_mut().end_address = 3 + 2 * cie.code_alignment_factor;
5379
        let instructions = [(Ok(true), CallFrameInstruction::AdvanceLoc { delta: 2 })];
5380
        assert_eval(ctx, expected, cie, None, instructions);
5381
    }
5382
5383
    #[test]
5384
    fn test_eval_advance_loc_overflow_32() {
5385
        let mut cie = make_test_cie();
5386
        cie.address_size = 4;
5387
        let mut ctx = UnwindContext::new();
5388
        ctx.row_mut().start_address = u32::MAX.into();
5389
        let expected = ctx.clone();
5390
        let instructions = [(
5391
            Err(Error::AddressOverflow),
5392
            CallFrameInstruction::AdvanceLoc { delta: 42 },
5393
        )];
5394
        assert_eval(ctx, expected, cie, None, instructions);
5395
    }
5396
5397
    #[test]
5398
    fn test_eval_advance_loc_overflow_64() {
5399
        let mut cie = make_test_cie();
5400
        cie.address_size = 8;
5401
        let mut ctx = UnwindContext::new();
5402
        ctx.row_mut().start_address = u64::MAX;
5403
        let expected = ctx.clone();
5404
        let instructions = [(
5405
            Err(Error::AddressOverflow),
5406
            CallFrameInstruction::AdvanceLoc { delta: 42 },
5407
        )];
5408
        assert_eval(ctx, expected, cie, None, instructions);
5409
    }
5410
5411
    #[test]
5412
    fn test_eval_def_cfa() {
5413
        let cie = make_test_cie();
5414
        let ctx = UnwindContext::new();
5415
        let mut expected = ctx.clone();
5416
        expected.set_cfa(CfaRule::RegisterAndOffset {
5417
            register: Register(42),
5418
            offset: 36,
5419
        });
5420
        let instructions = [(
5421
            Ok(false),
5422
            CallFrameInstruction::DefCfa {
5423
                register: Register(42),
5424
                offset: 36,
5425
            },
5426
        )];
5427
        assert_eval(ctx, expected, cie, None, instructions);
5428
    }
5429
5430
    #[test]
5431
    fn test_eval_def_cfa_sf() {
5432
        let cie = make_test_cie();
5433
        let ctx = UnwindContext::new();
5434
        let mut expected = ctx.clone();
5435
        expected.set_cfa(CfaRule::RegisterAndOffset {
5436
            register: Register(42),
5437
            offset: 36 * cie.data_alignment_factor as i64,
5438
        });
5439
        let instructions = [(
5440
            Ok(false),
5441
            CallFrameInstruction::DefCfaSf {
5442
                register: Register(42),
5443
                factored_offset: 36,
5444
            },
5445
        )];
5446
        assert_eval(ctx, expected, cie, None, instructions);
5447
    }
5448
5449
    #[test]
5450
    fn test_eval_def_cfa_register() {
5451
        let cie = make_test_cie();
5452
        let mut ctx = UnwindContext::new();
5453
        ctx.set_cfa(CfaRule::RegisterAndOffset {
5454
            register: Register(3),
5455
            offset: 8,
5456
        });
5457
        let mut expected = ctx.clone();
5458
        expected.set_cfa(CfaRule::RegisterAndOffset {
5459
            register: Register(42),
5460
            offset: 8,
5461
        });
5462
        let instructions = [(
5463
            Ok(false),
5464
            CallFrameInstruction::DefCfaRegister {
5465
                register: Register(42),
5466
            },
5467
        )];
5468
        assert_eval(ctx, expected, cie, None, instructions);
5469
    }
5470
5471
    #[test]
5472
    fn test_eval_def_cfa_register_invalid_context() {
5473
        let cie = make_test_cie();
5474
        let mut ctx = UnwindContext::new();
5475
        ctx.set_cfa(CfaRule::Expression(UnwindExpression {
5476
            offset: 0,
5477
            length: 0,
5478
        }));
5479
        let expected = ctx.clone();
5480
        let instructions = [(
5481
            Err(Error::CfiInstructionInInvalidContext),
5482
            CallFrameInstruction::DefCfaRegister {
5483
                register: Register(42),
5484
            },
5485
        )];
5486
        assert_eval(ctx, expected, cie, None, instructions);
5487
    }
5488
5489
    #[test]
5490
    fn test_eval_def_cfa_offset() {
5491
        let cie = make_test_cie();
5492
        let mut ctx = UnwindContext::new();
5493
        ctx.set_cfa(CfaRule::RegisterAndOffset {
5494
            register: Register(3),
5495
            offset: 8,
5496
        });
5497
        let mut expected = ctx.clone();
5498
        expected.set_cfa(CfaRule::RegisterAndOffset {
5499
            register: Register(3),
5500
            offset: 42,
5501
        });
5502
        let instructions = [(Ok(false), CallFrameInstruction::DefCfaOffset { offset: 42 })];
5503
        assert_eval(ctx, expected, cie, None, instructions);
5504
    }
5505
5506
    #[test]
5507
    fn test_eval_def_cfa_offset_invalid_context() {
5508
        let cie = make_test_cie();
5509
        let mut ctx = UnwindContext::new();
5510
        ctx.set_cfa(CfaRule::Expression(UnwindExpression {
5511
            offset: 10,
5512
            length: 11,
5513
        }));
5514
        let expected = ctx.clone();
5515
        let instructions = [(
5516
            Err(Error::CfiInstructionInInvalidContext),
5517
            CallFrameInstruction::DefCfaOffset { offset: 1993 },
5518
        )];
5519
        assert_eval(ctx, expected, cie, None, instructions);
5520
    }
5521
5522
    #[test]
5523
    fn test_eval_def_cfa_expression() {
5524
        let expr = UnwindExpression {
5525
            offset: 10,
5526
            length: 11,
5527
        };
5528
        let cie = make_test_cie();
5529
        let ctx = UnwindContext::new();
5530
        let mut expected = ctx.clone();
5531
        expected.set_cfa(CfaRule::Expression(expr));
5532
        let instructions = [(
5533
            Ok(false),
5534
            CallFrameInstruction::DefCfaExpression { expression: expr },
5535
        )];
5536
        assert_eval(ctx, expected, cie, None, instructions);
5537
    }
5538
5539
    #[test]
5540
    fn test_eval_undefined() {
5541
        let cie = make_test_cie();
5542
        let ctx = UnwindContext::new();
5543
        let mut expected = ctx.clone();
5544
        expected
5545
            .set_register_rule(Register(5), RegisterRule::Undefined)
5546
            .unwrap();
5547
        let instructions = [(
5548
            Ok(false),
5549
            CallFrameInstruction::Undefined {
5550
                register: Register(5),
5551
            },
5552
        )];
5553
        assert_eval(ctx, expected, cie, None, instructions);
5554
    }
5555
5556
    #[test]
5557
    fn test_eval_same_value() {
5558
        let cie = make_test_cie();
5559
        let ctx = UnwindContext::new();
5560
        let mut expected = ctx.clone();
5561
        expected
5562
            .set_register_rule(Register(0), RegisterRule::SameValue)
5563
            .unwrap();
5564
        let instructions = [(
5565
            Ok(false),
5566
            CallFrameInstruction::SameValue {
5567
                register: Register(0),
5568
            },
5569
        )];
5570
        assert_eval(ctx, expected, cie, None, instructions);
5571
    }
5572
5573
    #[test]
5574
    fn test_eval_offset() {
5575
        let cie = make_test_cie();
5576
        let ctx = UnwindContext::new();
5577
        let mut expected = ctx.clone();
5578
        expected
5579
            .set_register_rule(
5580
                Register(2),
5581
                RegisterRule::Offset(3 * cie.data_alignment_factor),
5582
            )
5583
            .unwrap();
5584
        let instructions = [(
5585
            Ok(false),
5586
            CallFrameInstruction::Offset {
5587
                register: Register(2),
5588
                factored_offset: 3,
5589
            },
5590
        )];
5591
        assert_eval(ctx, expected, cie, None, instructions);
5592
    }
5593
5594
    #[test]
5595
    fn test_eval_offset_extended_sf() {
5596
        let cie = make_test_cie();
5597
        let ctx = UnwindContext::new();
5598
        let mut expected = ctx.clone();
5599
        expected
5600
            .set_register_rule(
5601
                Register(4),
5602
                RegisterRule::Offset(-3 * cie.data_alignment_factor),
5603
            )
5604
            .unwrap();
5605
        let instructions = [(
5606
            Ok(false),
5607
            CallFrameInstruction::OffsetExtendedSf {
5608
                register: Register(4),
5609
                factored_offset: -3,
5610
            },
5611
        )];
5612
        assert_eval(ctx, expected, cie, None, instructions);
5613
    }
5614
5615
    #[test]
5616
    fn test_eval_val_offset() {
5617
        let cie = make_test_cie();
5618
        let ctx = UnwindContext::new();
5619
        let mut expected = ctx.clone();
5620
        expected
5621
            .set_register_rule(
5622
                Register(5),
5623
                RegisterRule::ValOffset(7 * cie.data_alignment_factor),
5624
            )
5625
            .unwrap();
5626
        let instructions = [(
5627
            Ok(false),
5628
            CallFrameInstruction::ValOffset {
5629
                register: Register(5),
5630
                factored_offset: 7,
5631
            },
5632
        )];
5633
        assert_eval(ctx, expected, cie, None, instructions);
5634
    }
5635
5636
    #[test]
5637
    fn test_eval_val_offset_sf() {
5638
        let cie = make_test_cie();
5639
        let ctx = UnwindContext::new();
5640
        let mut expected = ctx.clone();
5641
        expected
5642
            .set_register_rule(
5643
                Register(5),
5644
                RegisterRule::ValOffset(-7 * cie.data_alignment_factor),
5645
            )
5646
            .unwrap();
5647
        let instructions = [(
5648
            Ok(false),
5649
            CallFrameInstruction::ValOffsetSf {
5650
                register: Register(5),
5651
                factored_offset: -7,
5652
            },
5653
        )];
5654
        assert_eval(ctx, expected, cie, None, instructions);
5655
    }
5656
5657
    #[test]
5658
    fn test_eval_expression() {
5659
        let expr = UnwindExpression {
5660
            offset: 10,
5661
            length: 11,
5662
        };
5663
        let cie = make_test_cie();
5664
        let ctx = UnwindContext::new();
5665
        let mut expected = ctx.clone();
5666
        expected
5667
            .set_register_rule(Register(9), RegisterRule::Expression(expr))
5668
            .unwrap();
5669
        let instructions = [(
5670
            Ok(false),
5671
            CallFrameInstruction::Expression {
5672
                register: Register(9),
5673
                expression: expr,
5674
            },
5675
        )];
5676
        assert_eval(ctx, expected, cie, None, instructions);
5677
    }
5678
5679
    #[test]
5680
    fn test_eval_val_expression() {
5681
        let expr = UnwindExpression {
5682
            offset: 10,
5683
            length: 11,
5684
        };
5685
        let cie = make_test_cie();
5686
        let ctx = UnwindContext::new();
5687
        let mut expected = ctx.clone();
5688
        expected
5689
            .set_register_rule(Register(9), RegisterRule::ValExpression(expr))
5690
            .unwrap();
5691
        let instructions = [(
5692
            Ok(false),
5693
            CallFrameInstruction::ValExpression {
5694
                register: Register(9),
5695
                expression: expr,
5696
            },
5697
        )];
5698
        assert_eval(ctx, expected, cie, None, instructions);
5699
    }
5700
5701
    #[test]
5702
    fn test_eval_restore() {
5703
        let cie = make_test_cie();
5704
        let fde = FrameDescriptionEntry {
5705
            offset: 0,
5706
            format: Format::Dwarf64,
5707
            length: 0,
5708
            address_range: 0,
5709
            augmentation: None,
5710
            initial_address: 0,
5711
            cie: cie.clone(),
5712
            instructions: EndianSlice::new(&[], LittleEndian),
5713
        };
5714
5715
        let mut ctx = UnwindContext::new();
5716
        ctx.set_register_rule(Register(0), RegisterRule::Offset(1))
5717
            .unwrap();
5718
        ctx.save_initial_rules().unwrap();
5719
        let expected = ctx.clone();
5720
        ctx.set_register_rule(Register(0), RegisterRule::Offset(2))
5721
            .unwrap();
5722
5723
        let instructions = [(
5724
            Ok(false),
5725
            CallFrameInstruction::Restore {
5726
                register: Register(0),
5727
            },
5728
        )];
5729
        assert_eval(ctx, expected, cie, Some(fde), instructions);
5730
    }
5731
5732
    #[test]
5733
    fn test_eval_restore_havent_saved_initial_context() {
5734
        let cie = make_test_cie();
5735
        let ctx = UnwindContext::new();
5736
        let expected = ctx.clone();
5737
        let instructions = [(
5738
            Err(Error::CfiInstructionInInvalidContext),
5739
            CallFrameInstruction::Restore {
5740
                register: Register(0),
5741
            },
5742
        )];
5743
        assert_eval(ctx, expected, cie, None, instructions);
5744
    }
5745
5746
    #[test]
5747
    fn test_eval_remember_state() {
5748
        let cie = make_test_cie();
5749
        let ctx = UnwindContext::new();
5750
        let mut expected = ctx.clone();
5751
        expected.push_row().unwrap();
5752
        let instructions = [(Ok(false), CallFrameInstruction::RememberState)];
5753
        assert_eval(ctx, expected, cie, None, instructions);
5754
    }
5755
5756
    #[test]
5757
    fn test_eval_restore_state() {
5758
        let cie = make_test_cie();
5759
5760
        let mut ctx = UnwindContext::new();
5761
        ctx.set_start_address(1);
5762
        ctx.set_register_rule(Register(0), RegisterRule::SameValue)
5763
            .unwrap();
5764
        let mut expected = ctx.clone();
5765
        ctx.push_row().unwrap();
5766
        ctx.set_start_address(2);
5767
        ctx.set_register_rule(Register(0), RegisterRule::Offset(16))
5768
            .unwrap();
5769
5770
        // Restore state should preserve current location.
5771
        expected.set_start_address(2);
5772
5773
        let instructions = [
5774
            // First one pops just fine.
5775
            (Ok(false), CallFrameInstruction::RestoreState),
5776
            // Second pop would try to pop out of bounds.
5777
            (
5778
                Err(Error::PopWithEmptyStack),
5779
                CallFrameInstruction::RestoreState,
5780
            ),
5781
        ];
5782
5783
        assert_eval(ctx, expected, cie, None, instructions);
5784
    }
5785
5786
    #[test]
5787
    fn test_eval_negate_ra_state() {
5788
        let cie = make_test_cie();
5789
        let ctx = UnwindContext::new();
5790
        let mut expected = ctx.clone();
5791
        expected
5792
            .set_register_rule(crate::AArch64::RA_SIGN_STATE, RegisterRule::Constant(1))
5793
            .unwrap();
5794
        let instructions = [(Ok(false), CallFrameInstruction::NegateRaState)];
5795
        assert_eval(ctx, expected, cie, None, instructions);
5796
5797
        let cie = make_test_cie();
5798
        let ctx = UnwindContext::new();
5799
        let mut expected = ctx.clone();
5800
        expected
5801
            .set_register_rule(crate::AArch64::RA_SIGN_STATE, RegisterRule::Constant(0))
5802
            .unwrap();
5803
        let instructions = [
5804
            (Ok(false), CallFrameInstruction::NegateRaState),
5805
            (Ok(false), CallFrameInstruction::NegateRaState),
5806
        ];
5807
        assert_eval(ctx, expected, cie, None, instructions);
5808
5809
        // NegateRaState can't be used with other instructions.
5810
        let cie = make_test_cie();
5811
        let ctx = UnwindContext::new();
5812
        let mut expected = ctx.clone();
5813
        expected
5814
            .set_register_rule(
5815
                crate::AArch64::RA_SIGN_STATE,
5816
                RegisterRule::Offset(cie.data_alignment_factor as i64),
5817
            )
5818
            .unwrap();
5819
        let instructions = [
5820
            (
5821
                Ok(false),
5822
                CallFrameInstruction::Offset {
5823
                    register: crate::AArch64::RA_SIGN_STATE,
5824
                    factored_offset: 1,
5825
                },
5826
            ),
5827
            (
5828
                Err(Error::CfiInstructionInInvalidContext),
5829
                CallFrameInstruction::NegateRaState,
5830
            ),
5831
        ];
5832
        assert_eval(ctx, expected, cie, None, instructions);
5833
    }
5834
5835
    #[test]
5836
    fn test_eval_nop() {
5837
        let cie = make_test_cie();
5838
        let ctx = UnwindContext::new();
5839
        let expected = ctx.clone();
5840
        let instructions = [(Ok(false), CallFrameInstruction::Nop)];
5841
        assert_eval(ctx, expected, cie, None, instructions);
5842
    }
5843
5844
    #[test]
5845
    fn test_unwind_table_cie_no_rule() {
5846
        let initial_instructions = Section::with_endian(Endian::Little)
5847
            // The CFA is -12 from register 4.
5848
            .D8(constants::DW_CFA_def_cfa_sf.0)
5849
            .uleb(4)
5850
            .sleb(-12)
5851
            .append_repeated(constants::DW_CFA_nop.0, 4);
5852
        let initial_instructions = initial_instructions.get_contents().unwrap();
5853
5854
        let cie = CommonInformationEntry {
5855
            offset: 0,
5856
            length: 0,
5857
            format: Format::Dwarf32,
5858
            version: 4,
5859
            augmentation: None,
5860
            address_size: 8,
5861
            code_alignment_factor: 1,
5862
            data_alignment_factor: 1,
5863
            return_address_register: Register(3),
5864
            initial_instructions: EndianSlice::new(&initial_instructions, LittleEndian),
5865
        };
5866
5867
        let instructions = Section::with_endian(Endian::Little)
5868
            // A bunch of nop padding.
5869
            .append_repeated(constants::DW_CFA_nop.0, 8);
5870
        let instructions = instructions.get_contents().unwrap();
5871
5872
        let fde = FrameDescriptionEntry {
5873
            offset: 0,
5874
            length: 0,
5875
            format: Format::Dwarf32,
5876
            cie: cie.clone(),
5877
            initial_address: 0,
5878
            address_range: 100,
5879
            augmentation: None,
5880
            instructions: EndianSlice::new(&instructions, LittleEndian),
5881
        };
5882
5883
        let section = &DebugFrame::from(EndianSlice::default());
5884
        let bases = &BaseAddresses::default();
5885
        let mut ctx = Box::new(UnwindContext::new());
5886
5887
        let mut table = fde
5888
            .rows(section, bases, &mut ctx)
5889
            .expect("Should run initial program OK");
5890
        assert!(table.ctx.is_initialized);
5891
        let expected_initial_rule = (Register(0), RegisterRule::Undefined);
5892
        assert_eq!(table.ctx.initial_rule, Some(expected_initial_rule));
5893
5894
        {
5895
            let row = table.next_row().expect("Should evaluate first row OK");
5896
            let expected = UnwindTableRow {
5897
                start_address: 0,
5898
                end_address: 100,
5899
                saved_args_size: 0,
5900
                cfa: CfaRule::RegisterAndOffset {
5901
                    register: Register(4),
5902
                    offset: -12,
5903
                },
5904
                registers: [].iter().collect(),
5905
            };
5906
            assert_eq!(Some(&expected), row);
5907
        }
5908
5909
        // All done!
5910
        assert_eq!(Ok(None), table.next_row());
5911
        assert_eq!(Ok(None), table.next_row());
5912
    }
5913
5914
    #[test]
5915
    fn test_unwind_table_cie_single_rule() {
5916
        let initial_instructions = Section::with_endian(Endian::Little)
5917
            // The CFA is -12 from register 4.
5918
            .D8(constants::DW_CFA_def_cfa_sf.0)
5919
            .uleb(4)
5920
            .sleb(-12)
5921
            // Register 3 is 4 from the CFA.
5922
            .D8(constants::DW_CFA_offset.0 | 3)
5923
            .uleb(4)
5924
            .append_repeated(constants::DW_CFA_nop.0, 4);
5925
        let initial_instructions = initial_instructions.get_contents().unwrap();
5926
5927
        let cie = CommonInformationEntry {
5928
            offset: 0,
5929
            length: 0,
5930
            format: Format::Dwarf32,
5931
            version: 4,
5932
            augmentation: None,
5933
            address_size: 8,
5934
            code_alignment_factor: 1,
5935
            data_alignment_factor: 1,
5936
            return_address_register: Register(3),
5937
            initial_instructions: EndianSlice::new(&initial_instructions, LittleEndian),
5938
        };
5939
5940
        let instructions = Section::with_endian(Endian::Little)
5941
            // A bunch of nop padding.
5942
            .append_repeated(constants::DW_CFA_nop.0, 8);
5943
        let instructions = instructions.get_contents().unwrap();
5944
5945
        let fde = FrameDescriptionEntry {
5946
            offset: 0,
5947
            length: 0,
5948
            format: Format::Dwarf32,
5949
            cie: cie.clone(),
5950
            initial_address: 0,
5951
            address_range: 100,
5952
            augmentation: None,
5953
            instructions: EndianSlice::new(&instructions, LittleEndian),
5954
        };
5955
5956
        let section = &DebugFrame::from(EndianSlice::default());
5957
        let bases = &BaseAddresses::default();
5958
        let mut ctx = Box::new(UnwindContext::new());
5959
5960
        let mut table = fde
5961
            .rows(section, bases, &mut ctx)
5962
            .expect("Should run initial program OK");
5963
        assert!(table.ctx.is_initialized);
5964
        let expected_initial_rule = (Register(3), RegisterRule::Offset(4));
5965
        assert_eq!(table.ctx.initial_rule, Some(expected_initial_rule));
5966
5967
        {
5968
            let row = table.next_row().expect("Should evaluate first row OK");
5969
            let expected = UnwindTableRow {
5970
                start_address: 0,
5971
                end_address: 100,
5972
                saved_args_size: 0,
5973
                cfa: CfaRule::RegisterAndOffset {
5974
                    register: Register(4),
5975
                    offset: -12,
5976
                },
5977
                registers: [(Register(3), RegisterRule::Offset(4))].iter().collect(),
5978
            };
5979
            assert_eq!(Some(&expected), row);
5980
        }
5981
5982
        // All done!
5983
        assert_eq!(Ok(None), table.next_row());
5984
        assert_eq!(Ok(None), table.next_row());
5985
    }
5986
5987
    #[test]
5988
    fn test_unwind_table_cie_invalid_rule() {
5989
        let initial_instructions1 = Section::with_endian(Endian::Little)
5990
            // Test that stack length is reset.
5991
            .D8(constants::DW_CFA_remember_state.0)
5992
            // Test that stack value is reset (different register from that used later).
5993
            .D8(constants::DW_CFA_offset.0 | 4)
5994
            .uleb(8)
5995
            // Invalid due to missing operands.
5996
            .D8(constants::DW_CFA_offset.0);
5997
        let initial_instructions1 = initial_instructions1.get_contents().unwrap();
5998
5999
        let cie1 = CommonInformationEntry {
6000
            offset: 0,
6001
            length: 0,
6002
            format: Format::Dwarf32,
6003
            version: 4,
6004
            augmentation: None,
6005
            address_size: 8,
6006
            code_alignment_factor: 1,
6007
            data_alignment_factor: 1,
6008
            return_address_register: Register(3),
6009
            initial_instructions: EndianSlice::new(&initial_instructions1, LittleEndian),
6010
        };
6011
6012
        let initial_instructions2 = Section::with_endian(Endian::Little)
6013
            // Register 3 is 4 from the CFA.
6014
            .D8(constants::DW_CFA_offset.0 | 3)
6015
            .uleb(4)
6016
            .append_repeated(constants::DW_CFA_nop.0, 4);
6017
        let initial_instructions2 = initial_instructions2.get_contents().unwrap();
6018
6019
        let cie2 = CommonInformationEntry {
6020
            offset: 0,
6021
            length: 0,
6022
            format: Format::Dwarf32,
6023
            version: 4,
6024
            augmentation: None,
6025
            address_size: 8,
6026
            code_alignment_factor: 1,
6027
            data_alignment_factor: 1,
6028
            return_address_register: Register(3),
6029
            initial_instructions: EndianSlice::new(&initial_instructions2, LittleEndian),
6030
        };
6031
6032
        let fde1 = FrameDescriptionEntry {
6033
            offset: 0,
6034
            length: 0,
6035
            format: Format::Dwarf32,
6036
            cie: cie1.clone(),
6037
            initial_address: 0,
6038
            address_range: 100,
6039
            augmentation: None,
6040
            instructions: EndianSlice::new(&[], LittleEndian),
6041
        };
6042
6043
        let fde2 = FrameDescriptionEntry {
6044
            offset: 0,
6045
            length: 0,
6046
            format: Format::Dwarf32,
6047
            cie: cie2.clone(),
6048
            initial_address: 0,
6049
            address_range: 100,
6050
            augmentation: None,
6051
            instructions: EndianSlice::new(&[], LittleEndian),
6052
        };
6053
6054
        let section = &DebugFrame::from(EndianSlice::default());
6055
        let bases = &BaseAddresses::default();
6056
        let mut ctx = Box::new(UnwindContext::new());
6057
6058
        let table = fde1
6059
            .rows(section, bases, &mut ctx)
6060
            .map_eof(&initial_instructions1);
6061
        assert_eq!(table.err(), Some(Error::UnexpectedEof(ReaderOffsetId(4))));
6062
        assert!(!ctx.is_initialized);
6063
        assert_eq!(ctx.stack.len(), 2);
6064
        assert_eq!(ctx.initial_rule, None);
6065
6066
        let _table = fde2
6067
            .rows(section, bases, &mut ctx)
6068
            .expect("Should run initial program OK");
6069
        assert!(ctx.is_initialized);
6070
        assert_eq!(ctx.stack.len(), 1);
6071
        let expected_initial_rule = (Register(3), RegisterRule::Offset(4));
6072
        assert_eq!(ctx.initial_rule, Some(expected_initial_rule));
6073
    }
6074
6075
    #[test]
6076
    fn test_unwind_table_next_row() {
6077
        #[allow(clippy::identity_op)]
6078
        let initial_instructions = Section::with_endian(Endian::Little)
6079
            // The CFA is -12 from register 4.
6080
            .D8(constants::DW_CFA_def_cfa_sf.0)
6081
            .uleb(4)
6082
            .sleb(-12)
6083
            // Register 0 is 8 from the CFA.
6084
            .D8(constants::DW_CFA_offset.0 | 0)
6085
            .uleb(8)
6086
            // Register 3 is 4 from the CFA.
6087
            .D8(constants::DW_CFA_offset.0 | 3)
6088
            .uleb(4)
6089
            .append_repeated(constants::DW_CFA_nop.0, 4);
6090
        let initial_instructions = initial_instructions.get_contents().unwrap();
6091
6092
        let cie = CommonInformationEntry {
6093
            offset: 0,
6094
            length: 0,
6095
            format: Format::Dwarf32,
6096
            version: 4,
6097
            augmentation: None,
6098
            address_size: 8,
6099
            code_alignment_factor: 1,
6100
            data_alignment_factor: 1,
6101
            return_address_register: Register(3),
6102
            initial_instructions: EndianSlice::new(&initial_instructions, LittleEndian),
6103
        };
6104
6105
        let instructions = Section::with_endian(Endian::Little)
6106
            // Initial instructions form a row, advance the address by 1.
6107
            .D8(constants::DW_CFA_advance_loc1.0)
6108
            .D8(1)
6109
            // Register 0 is -16 from the CFA.
6110
            .D8(constants::DW_CFA_offset_extended_sf.0)
6111
            .uleb(0)
6112
            .sleb(-16)
6113
            // Finish this row, advance the address by 32.
6114
            .D8(constants::DW_CFA_advance_loc1.0)
6115
            .D8(32)
6116
            // Register 3 is -4 from the CFA.
6117
            .D8(constants::DW_CFA_offset_extended_sf.0)
6118
            .uleb(3)
6119
            .sleb(-4)
6120
            // Finish this row, advance the address by 64.
6121
            .D8(constants::DW_CFA_advance_loc1.0)
6122
            .D8(64)
6123
            // Register 5 is 4 from the CFA.
6124
            .D8(constants::DW_CFA_offset.0 | 5)
6125
            .uleb(4)
6126
            // A bunch of nop padding.
6127
            .append_repeated(constants::DW_CFA_nop.0, 8);
6128
        let instructions = instructions.get_contents().unwrap();
6129
6130
        let fde = FrameDescriptionEntry {
6131
            offset: 0,
6132
            length: 0,
6133
            format: Format::Dwarf32,
6134
            cie: cie.clone(),
6135
            initial_address: 0,
6136
            address_range: 100,
6137
            augmentation: None,
6138
            instructions: EndianSlice::new(&instructions, LittleEndian),
6139
        };
6140
6141
        let section = &DebugFrame::from(EndianSlice::default());
6142
        let bases = &BaseAddresses::default();
6143
        let mut ctx = Box::new(UnwindContext::new());
6144
6145
        let mut table = fde
6146
            .rows(section, bases, &mut ctx)
6147
            .expect("Should run initial program OK");
6148
        assert!(table.ctx.is_initialized);
6149
        assert!(table.ctx.initial_rule.is_none());
6150
        let expected_initial_rules: RegisterRuleMap<_> = [
6151
            (Register(0), RegisterRule::Offset(8)),
6152
            (Register(3), RegisterRule::Offset(4)),
6153
        ]
6154
        .iter()
6155
        .collect();
6156
        assert_eq!(table.ctx.stack[0].registers, expected_initial_rules);
6157
6158
        {
6159
            let row = table.next_row().expect("Should evaluate first row OK");
6160
            let expected = UnwindTableRow {
6161
                start_address: 0,
6162
                end_address: 1,
6163
                saved_args_size: 0,
6164
                cfa: CfaRule::RegisterAndOffset {
6165
                    register: Register(4),
6166
                    offset: -12,
6167
                },
6168
                registers: [
6169
                    (Register(0), RegisterRule::Offset(8)),
6170
                    (Register(3), RegisterRule::Offset(4)),
6171
                ]
6172
                .iter()
6173
                .collect(),
6174
            };
6175
            assert_eq!(Some(&expected), row);
6176
        }
6177
6178
        {
6179
            let row = table.next_row().expect("Should evaluate second row OK");
6180
            let expected = UnwindTableRow {
6181
                start_address: 1,
6182
                end_address: 33,
6183
                saved_args_size: 0,
6184
                cfa: CfaRule::RegisterAndOffset {
6185
                    register: Register(4),
6186
                    offset: -12,
6187
                },
6188
                registers: [
6189
                    (Register(0), RegisterRule::Offset(-16)),
6190
                    (Register(3), RegisterRule::Offset(4)),
6191
                ]
6192
                .iter()
6193
                .collect(),
6194
            };
6195
            assert_eq!(Some(&expected), row);
6196
        }
6197
6198
        {
6199
            let row = table.next_row().expect("Should evaluate third row OK");
6200
            let expected = UnwindTableRow {
6201
                start_address: 33,
6202
                end_address: 97,
6203
                saved_args_size: 0,
6204
                cfa: CfaRule::RegisterAndOffset {
6205
                    register: Register(4),
6206
                    offset: -12,
6207
                },
6208
                registers: [
6209
                    (Register(0), RegisterRule::Offset(-16)),
6210
                    (Register(3), RegisterRule::Offset(-4)),
6211
                ]
6212
                .iter()
6213
                .collect(),
6214
            };
6215
            assert_eq!(Some(&expected), row);
6216
        }
6217
6218
        {
6219
            let row = table.next_row().expect("Should evaluate fourth row OK");
6220
            let expected = UnwindTableRow {
6221
                start_address: 97,
6222
                end_address: 100,
6223
                saved_args_size: 0,
6224
                cfa: CfaRule::RegisterAndOffset {
6225
                    register: Register(4),
6226
                    offset: -12,
6227
                },
6228
                registers: [
6229
                    (Register(0), RegisterRule::Offset(-16)),
6230
                    (Register(3), RegisterRule::Offset(-4)),
6231
                    (Register(5), RegisterRule::Offset(4)),
6232
                ]
6233
                .iter()
6234
                .collect(),
6235
            };
6236
            assert_eq!(Some(&expected), row);
6237
        }
6238
6239
        // All done!
6240
        assert_eq!(Ok(None), table.next_row());
6241
        assert_eq!(Ok(None), table.next_row());
6242
    }
6243
6244
    #[test]
6245
    fn test_unwind_info_for_address_ok() {
6246
        let instrs1 = Section::with_endian(Endian::Big)
6247
            // The CFA is -12 from register 4.
6248
            .D8(constants::DW_CFA_def_cfa_sf.0)
6249
            .uleb(4)
6250
            .sleb(-12);
6251
        let instrs1 = instrs1.get_contents().unwrap();
6252
6253
        let instrs2: Vec<_> = (0..8).map(|_| constants::DW_CFA_nop.0).collect();
6254
6255
        let instrs3 = Section::with_endian(Endian::Big)
6256
            // Initial instructions form a row, advance the address by 100.
6257
            .D8(constants::DW_CFA_advance_loc1.0)
6258
            .D8(100)
6259
            // Register 0 is -16 from the CFA.
6260
            .D8(constants::DW_CFA_offset_extended_sf.0)
6261
            .uleb(0)
6262
            .sleb(-16);
6263
        let instrs3 = instrs3.get_contents().unwrap();
6264
6265
        let instrs4: Vec<_> = (0..16).map(|_| constants::DW_CFA_nop.0).collect();
6266
6267
        let mut cie1 = CommonInformationEntry {
6268
            offset: 0,
6269
            length: 0,
6270
            format: Format::Dwarf32,
6271
            version: 4,
6272
            augmentation: None,
6273
            address_size: 8,
6274
            code_alignment_factor: 1,
6275
            data_alignment_factor: 1,
6276
            return_address_register: Register(3),
6277
            initial_instructions: EndianSlice::new(&instrs1, BigEndian),
6278
        };
6279
6280
        let mut cie2 = CommonInformationEntry {
6281
            offset: 0,
6282
            length: 0,
6283
            format: Format::Dwarf32,
6284
            version: 4,
6285
            augmentation: None,
6286
            address_size: 4,
6287
            code_alignment_factor: 1,
6288
            data_alignment_factor: 1,
6289
            return_address_register: Register(1),
6290
            initial_instructions: EndianSlice::new(&instrs2, BigEndian),
6291
        };
6292
6293
        let cie1_location = Label::new();
6294
        let cie2_location = Label::new();
6295
6296
        // Write the CIEs first so that their length gets set before we clone
6297
        // them into the FDEs and our equality assertions down the line end up
6298
        // with all the CIEs always having he correct length.
6299
        let kind = debug_frame_be();
6300
        let section = Section::with_endian(kind.endian())
6301
            .mark(&cie1_location)
6302
            .cie(kind, None, &mut cie1)
6303
            .mark(&cie2_location)
6304
            .cie(kind, None, &mut cie2);
6305
6306
        let mut fde1 = FrameDescriptionEntry {
6307
            offset: 0,
6308
            length: 0,
6309
            format: Format::Dwarf32,
6310
            cie: cie1.clone(),
6311
            initial_address: 0xfeed_beef,
6312
            address_range: 200,
6313
            augmentation: None,
6314
            instructions: EndianSlice::new(&instrs3, BigEndian),
6315
        };
6316
6317
        let mut fde2 = FrameDescriptionEntry {
6318
            offset: 0,
6319
            length: 0,
6320
            format: Format::Dwarf32,
6321
            cie: cie2.clone(),
6322
            initial_address: 0xfeed_face,
6323
            address_range: 9000,
6324
            augmentation: None,
6325
            instructions: EndianSlice::new(&instrs4, BigEndian),
6326
        };
6327
6328
        let section =
6329
            section
6330
                .fde(kind, &cie1_location, &mut fde1)
6331
                .fde(kind, &cie2_location, &mut fde2);
6332
        section.start().set_const(0);
6333
6334
        let contents = section.get_contents().unwrap();
6335
        let debug_frame = kind.section(&contents);
6336
6337
        // Get the second row of the unwind table in `instrs3`.
6338
        let bases = Default::default();
6339
        let mut ctx = Box::new(UnwindContext::new());
6340
        let result = debug_frame.unwind_info_for_address(
6341
            &bases,
6342
            &mut ctx,
6343
            0xfeed_beef + 150,
6344
            DebugFrame::cie_from_offset,
6345
        );
6346
        assert!(result.is_ok());
6347
        let unwind_info = result.unwrap();
6348
6349
        assert_eq!(
6350
            *unwind_info,
6351
            UnwindTableRow {
6352
                start_address: fde1.initial_address() + 100,
6353
                end_address: fde1.end_address(),
6354
                saved_args_size: 0,
6355
                cfa: CfaRule::RegisterAndOffset {
6356
                    register: Register(4),
6357
                    offset: -12,
6358
                },
6359
                registers: [(Register(0), RegisterRule::Offset(-16))].iter().collect(),
6360
            }
6361
        );
6362
    }
6363
6364
    #[test]
6365
    fn test_unwind_info_for_address_not_found() {
6366
        let debug_frame = DebugFrame::new(&[], NativeEndian);
6367
        let bases = Default::default();
6368
        let mut ctx = Box::new(UnwindContext::new());
6369
        let result = debug_frame.unwind_info_for_address(
6370
            &bases,
6371
            &mut ctx,
6372
            0xbadb_ad99,
6373
            DebugFrame::cie_from_offset,
6374
        );
6375
        assert!(result.is_err());
6376
        assert_eq!(result.unwrap_err(), Error::NoUnwindInfoForAddress);
6377
    }
6378
6379
    #[test]
6380
    fn test_eh_frame_hdr_unknown_version() {
6381
        let bases = BaseAddresses::default();
6382
        let buf = &[42];
6383
        let result = EhFrameHdr::new(buf, NativeEndian).parse(&bases, 8);
6384
        assert!(result.is_err());
6385
        assert_eq!(result.unwrap_err(), Error::UnknownVersion(42));
6386
    }
6387
6388
    #[test]
6389
    fn test_eh_frame_hdr_omit_ehptr() {
6390
        let section = Section::with_endian(Endian::Little)
6391
            .L8(1)
6392
            .L8(0xff)
6393
            .L8(0x03)
6394
            .L8(0x0b)
6395
            .L32(2)
6396
            .L32(10)
6397
            .L32(1)
6398
            .L32(20)
6399
            .L32(2)
6400
            .L32(0);
6401
        let section = section.get_contents().unwrap();
6402
        let bases = BaseAddresses::default();
6403
        let result = EhFrameHdr::new(&section, LittleEndian).parse(&bases, 8);
6404
        assert!(result.is_err());
6405
        assert_eq!(result.unwrap_err(), Error::CannotParseOmitPointerEncoding);
6406
    }
6407
6408
    #[test]
6409
    fn test_eh_frame_hdr_omit_count() {
6410
        let section = Section::with_endian(Endian::Little)
6411
            .L8(1)
6412
            .L8(0x0b)
6413
            .L8(0xff)
6414
            .L8(0x0b)
6415
            .L32(0x12345);
6416
        let section = section.get_contents().unwrap();
6417
        let bases = BaseAddresses::default();
6418
        let result = EhFrameHdr::new(&section, LittleEndian).parse(&bases, 8);
6419
        assert!(result.is_ok());
6420
        let result = result.unwrap();
6421
        assert_eq!(result.eh_frame_ptr(), Pointer::Direct(0x12345));
6422
        assert!(result.table().is_none());
6423
    }
6424
6425
    #[test]
6426
    fn test_eh_frame_hdr_omit_table() {
6427
        let section = Section::with_endian(Endian::Little)
6428
            .L8(1)
6429
            .L8(0x0b)
6430
            .L8(0x03)
6431
            .L8(0xff)
6432
            .L32(0x12345)
6433
            .L32(2);
6434
        let section = section.get_contents().unwrap();
6435
        let bases = BaseAddresses::default();
6436
        let result = EhFrameHdr::new(&section, LittleEndian).parse(&bases, 8);
6437
        assert!(result.is_ok());
6438
        let result = result.unwrap();
6439
        assert_eq!(result.eh_frame_ptr(), Pointer::Direct(0x12345));
6440
        assert!(result.table().is_none());
6441
    }
6442
6443
    #[test]
6444
    fn test_eh_frame_hdr_varlen_table() {
6445
        let section = Section::with_endian(Endian::Little)
6446
            .L8(1)
6447
            .L8(0x0b)
6448
            .L8(0x03)
6449
            .L8(0x01)
6450
            .L32(0x12345)
6451
            .L32(2);
6452
        let section = section.get_contents().unwrap();
6453
        let bases = BaseAddresses::default();
6454
        let result = EhFrameHdr::new(&section, LittleEndian).parse(&bases, 8);
6455
        assert!(result.is_ok());
6456
        let result = result.unwrap();
6457
        assert_eq!(result.eh_frame_ptr(), Pointer::Direct(0x12345));
6458
        let table = result.table();
6459
        assert!(table.is_some());
6460
        let table = table.unwrap();
6461
        assert_eq!(
6462
            table.lookup(0, &bases),
6463
            Err(Error::VariableLengthSearchTable)
6464
        );
6465
    }
6466
6467
    #[test]
6468
    fn test_eh_frame_hdr_indirect_length() {
6469
        let section = Section::with_endian(Endian::Little)
6470
            .L8(1)
6471
            .L8(0x0b)
6472
            .L8(0x83)
6473
            .L8(0x0b)
6474
            .L32(0x12345)
6475
            .L32(2);
6476
        let section = section.get_contents().unwrap();
6477
        let bases = BaseAddresses::default();
6478
        let result = EhFrameHdr::new(&section, LittleEndian).parse(&bases, 8);
6479
        assert!(result.is_err());
6480
        assert_eq!(result.unwrap_err(), Error::UnsupportedPointerEncoding);
6481
    }
6482
6483
    #[test]
6484
    fn test_eh_frame_hdr_indirect_ptrs() {
6485
        let section = Section::with_endian(Endian::Little)
6486
            .L8(1)
6487
            .L8(0x8b)
6488
            .L8(0x03)
6489
            .L8(0x8b)
6490
            .L32(0x12345)
6491
            .L32(2)
6492
            .L32(10)
6493
            .L32(1)
6494
            .L32(20)
6495
            .L32(2);
6496
        let section = section.get_contents().unwrap();
6497
        let bases = BaseAddresses::default();
6498
        let result = EhFrameHdr::new(&section, LittleEndian).parse(&bases, 8);
6499
        assert!(result.is_ok());
6500
        let result = result.unwrap();
6501
        assert_eq!(result.eh_frame_ptr(), Pointer::Indirect(0x12345));
6502
        let table = result.table();
6503
        assert!(table.is_some());
6504
        let table = table.unwrap();
6505
        assert_eq!(
6506
            table.lookup(0, &bases),
6507
            Err(Error::UnsupportedPointerEncoding)
6508
        );
6509
    }
6510
6511
    #[test]
6512
    fn test_eh_frame_hdr_good() {
6513
        let section = Section::with_endian(Endian::Little)
6514
            .L8(1)
6515
            .L8(0x0b)
6516
            .L8(0x03)
6517
            .L8(0x0b)
6518
            .L32(0x12345)
6519
            .L32(2)
6520
            .L32(10)
6521
            .L32(1)
6522
            .L32(20)
6523
            .L32(2);
6524
        let section = section.get_contents().unwrap();
6525
        let bases = BaseAddresses::default();
6526
        let result = EhFrameHdr::new(&section, LittleEndian).parse(&bases, 8);
6527
        assert!(result.is_ok());
6528
        let result = result.unwrap();
6529
        assert_eq!(result.eh_frame_ptr(), Pointer::Direct(0x12345));
6530
        let table = result.table();
6531
        assert!(table.is_some());
6532
        let table = table.unwrap();
6533
        assert_eq!(table.lookup(0, &bases), Ok(Pointer::Direct(1)));
6534
        assert_eq!(table.lookup(9, &bases), Ok(Pointer::Direct(1)));
6535
        assert_eq!(table.lookup(10, &bases), Ok(Pointer::Direct(1)));
6536
        assert_eq!(table.lookup(11, &bases), Ok(Pointer::Direct(1)));
6537
        assert_eq!(table.lookup(19, &bases), Ok(Pointer::Direct(1)));
6538
        assert_eq!(table.lookup(20, &bases), Ok(Pointer::Direct(2)));
6539
        assert_eq!(table.lookup(21, &bases), Ok(Pointer::Direct(2)));
6540
        assert_eq!(table.lookup(100_000, &bases), Ok(Pointer::Direct(2)));
6541
    }
6542
6543
    #[test]
6544
    fn test_eh_frame_fde_for_address_good() {
6545
        // First, setup eh_frame
6546
        // Write the CIE first so that its length gets set before we clone it
6547
        // into the FDE.
6548
        let mut cie = make_test_cie();
6549
        cie.format = Format::Dwarf32;
6550
        cie.version = 1;
6551
6552
        let start_of_cie = Label::new();
6553
        let end_of_cie = Label::new();
6554
6555
        let kind = eh_frame_le();
6556
        let section = Section::with_endian(kind.endian())
6557
            .append_repeated(0, 16)
6558
            .mark(&start_of_cie)
6559
            .cie(kind, None, &mut cie)
6560
            .mark(&end_of_cie);
6561
6562
        let mut fde1 = FrameDescriptionEntry {
6563
            offset: 0,
6564
            length: 0,
6565
            format: Format::Dwarf32,
6566
            cie: cie.clone(),
6567
            initial_address: 9,
6568
            address_range: 4,
6569
            augmentation: None,
6570
            instructions: EndianSlice::new(&[], LittleEndian),
6571
        };
6572
        let mut fde2 = FrameDescriptionEntry {
6573
            offset: 0,
6574
            length: 0,
6575
            format: Format::Dwarf32,
6576
            cie: cie.clone(),
6577
            initial_address: 20,
6578
            address_range: 8,
6579
            augmentation: None,
6580
            instructions: EndianSlice::new(&[], LittleEndian),
6581
        };
6582
6583
        let start_of_fde1 = Label::new();
6584
        let start_of_fde2 = Label::new();
6585
6586
        let section = section
6587
            // +4 for the FDE length before the CIE offset.
6588
            .mark(&start_of_fde1)
6589
            .fde(kind, (&start_of_fde1 - &start_of_cie + 4) as u64, &mut fde1)
6590
            .mark(&start_of_fde2)
6591
            .fde(kind, (&start_of_fde2 - &start_of_cie + 4) as u64, &mut fde2);
6592
6593
        section.start().set_const(0);
6594
        let section = section.get_contents().unwrap();
6595
        let eh_frame = kind.section(&section);
6596
6597
        // Setup eh_frame_hdr
6598
        let section = Section::with_endian(kind.endian())
6599
            .L8(1)
6600
            .L8(0x0b)
6601
            .L8(0x03)
6602
            .L8(0x0b)
6603
            .L32(0x12345)
6604
            .L32(2)
6605
            .L32(10)
6606
            .L32(0x12345 + start_of_fde1.value().unwrap() as u32)
6607
            .L32(20)
6608
            .L32(0x12345 + start_of_fde2.value().unwrap() as u32);
6609
6610
        let section = section.get_contents().unwrap();
6611
        let bases = BaseAddresses::default();
6612
        let eh_frame_hdr = EhFrameHdr::new(&section, LittleEndian).parse(&bases, 8);
6613
        assert!(eh_frame_hdr.is_ok());
6614
        let eh_frame_hdr = eh_frame_hdr.unwrap();
6615
6616
        let table = eh_frame_hdr.table();
6617
        assert!(table.is_some());
6618
        let table = table.unwrap();
6619
6620
        let bases = Default::default();
6621
        let mut iter = table.iter(&bases);
6622
        assert_eq!(
6623
            iter.next(),
6624
            Ok(Some((
6625
                Pointer::Direct(10),
6626
                Pointer::Direct(0x12345 + start_of_fde1.value().unwrap())
6627
            )))
6628
        );
6629
        assert_eq!(
6630
            iter.next(),
6631
            Ok(Some((
6632
                Pointer::Direct(20),
6633
                Pointer::Direct(0x12345 + start_of_fde2.value().unwrap())
6634
            )))
6635
        );
6636
        assert_eq!(iter.next(), Ok(None));
6637
6638
        assert_eq!(
6639
            table.iter(&bases).nth(0),
6640
            Ok(Some((
6641
                Pointer::Direct(10),
6642
                Pointer::Direct(0x12345 + start_of_fde1.value().unwrap())
6643
            )))
6644
        );
6645
6646
        assert_eq!(
6647
            table.iter(&bases).nth(1),
6648
            Ok(Some((
6649
                Pointer::Direct(20),
6650
                Pointer::Direct(0x12345 + start_of_fde2.value().unwrap())
6651
            )))
6652
        );
6653
        assert_eq!(table.iter(&bases).nth(2), Ok(None));
6654
6655
        let f = |_: &_, _: &_, o: EhFrameOffset| {
6656
            assert_eq!(o, EhFrameOffset(start_of_cie.value().unwrap() as usize));
6657
            Ok(cie.clone())
6658
        };
6659
        assert_eq!(
6660
            table.fde_for_address(&eh_frame, &bases, 9, f),
6661
            Ok(fde1.clone())
6662
        );
6663
        assert_eq!(
6664
            table.fde_for_address(&eh_frame, &bases, 10, f),
6665
            Ok(fde1.clone())
6666
        );
6667
        assert_eq!(table.fde_for_address(&eh_frame, &bases, 11, f), Ok(fde1));
6668
        assert_eq!(
6669
            table.fde_for_address(&eh_frame, &bases, 19, f),
6670
            Err(Error::NoUnwindInfoForAddress)
6671
        );
6672
        assert_eq!(
6673
            table.fde_for_address(&eh_frame, &bases, 20, f),
6674
            Ok(fde2.clone())
6675
        );
6676
        assert_eq!(table.fde_for_address(&eh_frame, &bases, 21, f), Ok(fde2));
6677
        assert_eq!(
6678
            table.fde_for_address(&eh_frame, &bases, 100_000, f),
6679
            Err(Error::NoUnwindInfoForAddress)
6680
        );
6681
    }
6682
6683
    #[test]
6684
    fn test_eh_frame_stops_at_zero_length() {
6685
        let mut cie = make_test_cie();
6686
        let kind = eh_frame_le();
6687
        let section = Section::with_endian(Endian::Little)
6688
            .L32(0)
6689
            .cie(kind, None, &mut cie)
6690
            .L32(0);
6691
        let contents = section.get_contents().unwrap();
6692
        let eh_frame = kind.section(&contents);
6693
        let bases = Default::default();
6694
6695
        let mut entries = eh_frame.entries(&bases);
6696
        assert_eq!(entries.next(), Ok(None));
6697
6698
        assert_eq!(
6699
            eh_frame.cie_from_offset(&bases, EhFrameOffset(0)),
6700
            Err(Error::NoEntryAtGivenOffset)
6701
        );
6702
    }
6703
6704
    #[test]
6705
    fn test_debug_frame_skips_zero_length() {
6706
        let mut cie = make_test_cie();
6707
        let kind = debug_frame_le();
6708
        let section = Section::with_endian(Endian::Little)
6709
            .L32(0)
6710
            .cie(kind, None, &mut cie)
6711
            .L32(0);
6712
        let contents = section.get_contents().unwrap();
6713
        let debug_frame = kind.section(&contents);
6714
        let bases = Default::default();
6715
6716
        let mut entries = debug_frame.entries(&bases);
6717
        assert_eq!(entries.next(), Ok(Some(CieOrFde::Cie(cie))));
6718
        assert_eq!(entries.next(), Ok(None));
6719
6720
        assert_eq!(
6721
            debug_frame.cie_from_offset(&bases, DebugFrameOffset(0)),
6722
            Err(Error::NoEntryAtGivenOffset)
6723
        );
6724
    }
6725
6726
    fn resolve_cie_offset(buf: &[u8], cie_offset: usize) -> Result<usize> {
6727
        let mut fde = FrameDescriptionEntry {
6728
            offset: 0,
6729
            length: 0,
6730
            format: Format::Dwarf64,
6731
            cie: make_test_cie(),
6732
            initial_address: 0xfeed_beef,
6733
            address_range: 39,
6734
            augmentation: None,
6735
            instructions: EndianSlice::new(&[], LittleEndian),
6736
        };
6737
6738
        let kind = eh_frame_le();
6739
        let section = Section::with_endian(kind.endian())
6740
            .append_bytes(buf)
6741
            .fde(kind, cie_offset as u64, &mut fde)
6742
            .append_bytes(buf);
6743
6744
        let section = section.get_contents().unwrap();
6745
        let eh_frame = kind.section(&section);
6746
        let input = &mut EndianSlice::new(&section[buf.len()..], LittleEndian);
6747
6748
        let bases = Default::default();
6749
        match parse_cfi_entry(&bases, &eh_frame, input) {
6750
            Ok(Some(CieOrFde::Fde(partial))) => Ok(partial.cie_offset.0),
6751
            Err(e) => Err(e),
6752
            otherwise => panic!("Unexpected result: {:#?}", otherwise),
6753
        }
6754
    }
6755
6756
    #[test]
6757
    fn test_eh_frame_resolve_cie_offset_ok() {
6758
        let buf = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
6759
        let cie_offset = 2;
6760
        // + 4 for size of length field
6761
        assert_eq!(
6762
            resolve_cie_offset(&buf, buf.len() + 4 - cie_offset),
6763
            Ok(cie_offset)
6764
        );
6765
    }
6766
6767
    #[test]
6768
    fn test_eh_frame_resolve_cie_offset_out_of_bounds() {
6769
        let buf = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
6770
        assert_eq!(
6771
            resolve_cie_offset(&buf, buf.len() + 4 + 2),
6772
            Err(Error::OffsetOutOfBounds)
6773
        );
6774
    }
6775
6776
    #[test]
6777
    fn test_eh_frame_resolve_cie_offset_underflow() {
6778
        let buf = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
6779
        assert_eq!(
6780
            resolve_cie_offset(&buf, usize::MAX),
6781
            Err(Error::OffsetOutOfBounds)
6782
        );
6783
    }
6784
6785
    #[test]
6786
    fn test_eh_frame_fde_ok() {
6787
        let mut cie = make_test_cie();
6788
        cie.format = Format::Dwarf32;
6789
        cie.version = 1;
6790
6791
        let start_of_cie = Label::new();
6792
        let end_of_cie = Label::new();
6793
6794
        // Write the CIE first so that its length gets set before we clone it
6795
        // into the FDE.
6796
        let kind = eh_frame_le();
6797
        let section = Section::with_endian(kind.endian())
6798
            .append_repeated(0, 16)
6799
            .mark(&start_of_cie)
6800
            .cie(kind, None, &mut cie)
6801
            .mark(&end_of_cie);
6802
6803
        let mut fde = FrameDescriptionEntry {
6804
            offset: 0,
6805
            length: 0,
6806
            format: Format::Dwarf32,
6807
            cie: cie.clone(),
6808
            initial_address: 0xfeed_beef,
6809
            address_range: 999,
6810
            augmentation: None,
6811
            instructions: EndianSlice::new(&[], LittleEndian),
6812
        };
6813
6814
        let section = section
6815
            // +4 for the FDE length before the CIE offset.
6816
            .fde(kind, (&end_of_cie - &start_of_cie + 4) as u64, &mut fde);
6817
6818
        section.start().set_const(0);
6819
        let section = section.get_contents().unwrap();
6820
        let eh_frame = kind.section(&section);
6821
        let section = EndianSlice::new(&section, LittleEndian);
6822
6823
        let mut offset = None;
6824
        let result = parse_fde(
6825
            eh_frame,
6826
            &mut section.range_from(end_of_cie.value().unwrap() as usize..),
6827
            |_, _, o| {
6828
                offset = Some(o);
6829
                assert_eq!(o, EhFrameOffset(start_of_cie.value().unwrap() as usize));
6830
                Ok(cie.clone())
6831
            },
6832
        );
6833
        match result {
6834
            Ok(actual) => assert_eq!(actual, fde),
6835
            otherwise => panic!("Unexpected result {:?}", otherwise),
6836
        }
6837
        assert!(offset.is_some());
6838
    }
6839
6840
    #[test]
6841
    fn test_eh_frame_fde_out_of_bounds() {
6842
        let mut cie = make_test_cie();
6843
        cie.version = 1;
6844
6845
        let end_of_cie = Label::new();
6846
6847
        let mut fde = FrameDescriptionEntry {
6848
            offset: 0,
6849
            length: 0,
6850
            format: Format::Dwarf64,
6851
            cie: cie.clone(),
6852
            initial_address: 0xfeed_beef,
6853
            address_range: 999,
6854
            augmentation: None,
6855
            instructions: EndianSlice::new(&[], LittleEndian),
6856
        };
6857
6858
        let kind = eh_frame_le();
6859
        let section = Section::with_endian(kind.endian())
6860
            .cie(kind, None, &mut cie)
6861
            .mark(&end_of_cie)
6862
            .fde(kind, 99_999_999_999_999, &mut fde);
6863
6864
        section.start().set_const(0);
6865
        let section = section.get_contents().unwrap();
6866
        let eh_frame = kind.section(&section);
6867
        let section = EndianSlice::new(&section, LittleEndian);
6868
6869
        let result = parse_fde(
6870
            eh_frame,
6871
            &mut section.range_from(end_of_cie.value().unwrap() as usize..),
6872
            UnwindSection::cie_from_offset,
6873
        );
6874
        assert_eq!(result, Err(Error::OffsetOutOfBounds));
6875
    }
6876
6877
    #[test]
6878
    fn test_augmentation_parse_not_z_augmentation() {
6879
        let augmentation = &mut EndianSlice::new(b"wtf", NativeEndian);
6880
        let bases = Default::default();
6881
        let address_size = 8;
6882
        let section = EhFrame::new(&[], NativeEndian);
6883
        let input = &mut EndianSlice::new(&[], NativeEndian);
6884
        assert_eq!(
6885
            Augmentation::parse(augmentation, &bases, address_size, &section, input),
6886
            Err(Error::UnknownAugmentation)
6887
        );
6888
    }
6889
6890
    #[test]
6891
    fn test_augmentation_parse_just_signal_trampoline() {
6892
        let aug_str = &mut EndianSlice::new(b"S", LittleEndian);
6893
        let bases = Default::default();
6894
        let address_size = 8;
6895
        let section = EhFrame::new(&[], LittleEndian);
6896
        let input = &mut EndianSlice::new(&[], LittleEndian);
6897
6898
        let augmentation = Augmentation {
6899
            is_signal_trampoline: true,
6900
            ..Default::default()
6901
        };
6902
6903
        assert_eq!(
6904
            Augmentation::parse(aug_str, &bases, address_size, &section, input),
6905
            Ok(augmentation)
6906
        );
6907
    }
6908
6909
    #[test]
6910
    fn test_augmentation_parse_unknown_part_of_z_augmentation() {
6911
        // The 'Z' character is not defined by the z-style augmentation.
6912
        let bases = Default::default();
6913
        let address_size = 8;
6914
        let section = Section::with_endian(Endian::Little)
6915
            .uleb(4)
6916
            .append_repeated(4, 4)
6917
            .get_contents()
6918
            .unwrap();
6919
        let section = EhFrame::new(&section, LittleEndian);
6920
        let input = &mut section.section().clone();
6921
        let augmentation = &mut EndianSlice::new(b"zZ", LittleEndian);
6922
        assert_eq!(
6923
            Augmentation::parse(augmentation, &bases, address_size, &section, input),
6924
            Err(Error::UnknownAugmentation)
6925
        );
6926
    }
6927
6928
    #[test]
6929
    #[allow(non_snake_case)]
6930
    fn test_augmentation_parse_L() {
6931
        let bases = Default::default();
6932
        let address_size = 8;
6933
        let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1];
6934
6935
        let section = Section::with_endian(Endian::Little)
6936
            .uleb(1)
6937
            .D8(constants::DW_EH_PE_uleb128.0)
6938
            .append_bytes(&rest)
6939
            .get_contents()
6940
            .unwrap();
6941
        let section = EhFrame::new(&section, LittleEndian);
6942
        let input = &mut section.section().clone();
6943
        let aug_str = &mut EndianSlice::new(b"zL", LittleEndian);
6944
6945
        let augmentation = Augmentation {
6946
            lsda: Some(constants::DW_EH_PE_uleb128),
6947
            ..Default::default()
6948
        };
6949
6950
        assert_eq!(
6951
            Augmentation::parse(aug_str, &bases, address_size, &section, input),
6952
            Ok(augmentation)
6953
        );
6954
        assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
6955
    }
6956
6957
    #[test]
6958
    #[allow(non_snake_case)]
6959
    fn test_augmentation_parse_P() {
6960
        let bases = Default::default();
6961
        let address_size = 8;
6962
        let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1];
6963
6964
        let section = Section::with_endian(Endian::Little)
6965
            .uleb(9)
6966
            .D8(constants::DW_EH_PE_udata8.0)
6967
            .L64(0xf00d_f00d)
6968
            .append_bytes(&rest)
6969
            .get_contents()
6970
            .unwrap();
6971
        let section = EhFrame::new(&section, LittleEndian);
6972
        let input = &mut section.section().clone();
6973
        let aug_str = &mut EndianSlice::new(b"zP", LittleEndian);
6974
6975
        let augmentation = Augmentation {
6976
            personality: Some((constants::DW_EH_PE_udata8, Pointer::Direct(0xf00d_f00d))),
6977
            ..Default::default()
6978
        };
6979
6980
        assert_eq!(
6981
            Augmentation::parse(aug_str, &bases, address_size, &section, input),
6982
            Ok(augmentation)
6983
        );
6984
        assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
6985
    }
6986
6987
    #[test]
6988
    #[allow(non_snake_case)]
6989
    fn test_augmentation_parse_R() {
6990
        let bases = Default::default();
6991
        let address_size = 8;
6992
        let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1];
6993
6994
        let section = Section::with_endian(Endian::Little)
6995
            .uleb(1)
6996
            .D8(constants::DW_EH_PE_udata4.0)
6997
            .append_bytes(&rest)
6998
            .get_contents()
6999
            .unwrap();
7000
        let section = EhFrame::new(&section, LittleEndian);
7001
        let input = &mut section.section().clone();
7002
        let aug_str = &mut EndianSlice::new(b"zR", LittleEndian);
7003
7004
        let augmentation = Augmentation {
7005
            fde_address_encoding: Some(constants::DW_EH_PE_udata4),
7006
            ..Default::default()
7007
        };
7008
7009
        assert_eq!(
7010
            Augmentation::parse(aug_str, &bases, address_size, &section, input),
7011
            Ok(augmentation)
7012
        );
7013
        assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
7014
    }
7015
7016
    #[test]
7017
    #[allow(non_snake_case)]
7018
    fn test_augmentation_parse_S() {
7019
        let bases = Default::default();
7020
        let address_size = 8;
7021
        let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1];
7022
7023
        let section = Section::with_endian(Endian::Little)
7024
            .uleb(0)
7025
            .append_bytes(&rest)
7026
            .get_contents()
7027
            .unwrap();
7028
        let section = EhFrame::new(&section, LittleEndian);
7029
        let input = &mut section.section().clone();
7030
        let aug_str = &mut EndianSlice::new(b"zS", LittleEndian);
7031
7032
        let augmentation = Augmentation {
7033
            is_signal_trampoline: true,
7034
            ..Default::default()
7035
        };
7036
7037
        assert_eq!(
7038
            Augmentation::parse(aug_str, &bases, address_size, &section, input),
7039
            Ok(augmentation)
7040
        );
7041
        assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
7042
    }
7043
7044
    #[test]
7045
    fn test_augmentation_parse_all() {
7046
        let bases = Default::default();
7047
        let address_size = 8;
7048
        let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1];
7049
7050
        let section = Section::with_endian(Endian::Little)
7051
            .uleb(1 + 9 + 1)
7052
            // L
7053
            .D8(constants::DW_EH_PE_uleb128.0)
7054
            // P
7055
            .D8(constants::DW_EH_PE_udata8.0)
7056
            .L64(0x1bad_f00d)
7057
            // R
7058
            .D8(constants::DW_EH_PE_uleb128.0)
7059
            .append_bytes(&rest)
7060
            .get_contents()
7061
            .unwrap();
7062
        let section = EhFrame::new(&section, LittleEndian);
7063
        let input = &mut section.section().clone();
7064
        let aug_str = &mut EndianSlice::new(b"zLPRS", LittleEndian);
7065
7066
        let augmentation = Augmentation {
7067
            lsda: Some(constants::DW_EH_PE_uleb128),
7068
            personality: Some((constants::DW_EH_PE_udata8, Pointer::Direct(0x1bad_f00d))),
7069
            fde_address_encoding: Some(constants::DW_EH_PE_uleb128),
7070
            is_signal_trampoline: true,
7071
        };
7072
7073
        assert_eq!(
7074
            Augmentation::parse(aug_str, &bases, address_size, &section, input),
7075
            Ok(augmentation)
7076
        );
7077
        assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
7078
    }
7079
7080
    #[test]
7081
    fn test_eh_frame_fde_no_augmentation() {
7082
        let instrs = [1, 2, 3, 4];
7083
        let cie_offset = 1;
7084
7085
        let mut cie = make_test_cie();
7086
        cie.format = Format::Dwarf32;
7087
        cie.version = 1;
7088
7089
        let mut fde = FrameDescriptionEntry {
7090
            offset: 0,
7091
            length: 0,
7092
            format: Format::Dwarf32,
7093
            cie: cie.clone(),
7094
            initial_address: 0xfeed_face,
7095
            address_range: 9000,
7096
            augmentation: None,
7097
            instructions: EndianSlice::new(&instrs, LittleEndian),
7098
        };
7099
7100
        let rest = [1, 2, 3, 4];
7101
7102
        let kind = eh_frame_le();
7103
        let section = Section::with_endian(kind.endian())
7104
            .fde(kind, cie_offset, &mut fde)
7105
            .append_bytes(&rest)
7106
            .get_contents()
7107
            .unwrap();
7108
        let section = kind.section(&section);
7109
        let input = &mut section.section().clone();
7110
7111
        let result = parse_fde(section, input, |_, _, _| Ok(cie.clone()));
7112
        assert_eq!(result, Ok(fde));
7113
        assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
7114
    }
7115
7116
    #[test]
7117
    fn test_eh_frame_fde_empty_augmentation() {
7118
        let instrs = [1, 2, 3, 4];
7119
        let cie_offset = 1;
7120
7121
        let mut cie = make_test_cie();
7122
        cie.format = Format::Dwarf32;
7123
        cie.version = 1;
7124
        cie.augmentation = Some(Augmentation::default());
7125
7126
        let mut fde = FrameDescriptionEntry {
7127
            offset: 0,
7128
            length: 0,
7129
            format: Format::Dwarf32,
7130
            cie: cie.clone(),
7131
            initial_address: 0xfeed_face,
7132
            address_range: 9000,
7133
            augmentation: Some(AugmentationData::default()),
7134
            instructions: EndianSlice::new(&instrs, LittleEndian),
7135
        };
7136
7137
        let rest = [1, 2, 3, 4];
7138
7139
        let kind = eh_frame_le();
7140
        let section = Section::with_endian(kind.endian())
7141
            .fde(kind, cie_offset, &mut fde)
7142
            .append_bytes(&rest)
7143
            .get_contents()
7144
            .unwrap();
7145
        let section = kind.section(&section);
7146
        let input = &mut section.section().clone();
7147
7148
        let result = parse_fde(section, input, |_, _, _| Ok(cie.clone()));
7149
        assert_eq!(result, Ok(fde));
7150
        assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
7151
    }
7152
7153
    #[test]
7154
    fn test_eh_frame_fde_lsda_augmentation() {
7155
        let instrs = [1, 2, 3, 4];
7156
        let cie_offset = 1;
7157
7158
        let mut cie = make_test_cie();
7159
        cie.format = Format::Dwarf32;
7160
        cie.version = 1;
7161
        cie.augmentation = Some(Augmentation::default());
7162
        cie.augmentation.as_mut().unwrap().lsda = Some(constants::DW_EH_PE_absptr);
7163
7164
        let mut fde = FrameDescriptionEntry {
7165
            offset: 0,
7166
            length: 0,
7167
            format: Format::Dwarf32,
7168
            cie: cie.clone(),
7169
            initial_address: 0xfeed_face,
7170
            address_range: 9000,
7171
            augmentation: Some(AugmentationData {
7172
                lsda: Some(Pointer::Direct(0x1122_3344)),
7173
            }),
7174
            instructions: EndianSlice::new(&instrs, LittleEndian),
7175
        };
7176
7177
        let rest = [1, 2, 3, 4];
7178
7179
        let kind = eh_frame_le();
7180
        let section = Section::with_endian(kind.endian())
7181
            .fde(kind, cie_offset, &mut fde)
7182
            .append_bytes(&rest)
7183
            .get_contents()
7184
            .unwrap();
7185
        let section = kind.section(&section);
7186
        let input = &mut section.section().clone();
7187
7188
        let result = parse_fde(section, input, |_, _, _| Ok(cie.clone()));
7189
        assert_eq!(result, Ok(fde));
7190
        assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
7191
    }
7192
7193
    #[test]
7194
    fn test_eh_frame_fde_lsda_function_relative() {
7195
        let instrs = [1, 2, 3, 4];
7196
        let cie_offset = 1;
7197
7198
        let mut cie = make_test_cie();
7199
        cie.format = Format::Dwarf32;
7200
        cie.version = 1;
7201
        cie.augmentation = Some(Augmentation::default());
7202
        cie.augmentation.as_mut().unwrap().lsda =
7203
            Some(constants::DW_EH_PE_funcrel | constants::DW_EH_PE_absptr);
7204
7205
        let mut fde = FrameDescriptionEntry {
7206
            offset: 0,
7207
            length: 0,
7208
            format: Format::Dwarf32,
7209
            cie: cie.clone(),
7210
            initial_address: 0xfeed_face,
7211
            address_range: 9000,
7212
            augmentation: Some(AugmentationData {
7213
                lsda: Some(Pointer::Direct(0xbeef)),
7214
            }),
7215
            instructions: EndianSlice::new(&instrs, LittleEndian),
7216
        };
7217
7218
        let rest = [1, 2, 3, 4];
7219
7220
        let kind = eh_frame_le();
7221
        let section = Section::with_endian(kind.endian())
7222
            .append_repeated(10, 10)
7223
            .fde(kind, cie_offset, &mut fde)
7224
            .append_bytes(&rest)
7225
            .get_contents()
7226
            .unwrap();
7227
        let section = kind.section(&section);
7228
        let input = &mut section.section().range_from(10..);
7229
7230
        // Adjust the FDE's augmentation to be relative to the function.
7231
        fde.augmentation.as_mut().unwrap().lsda = Some(Pointer::Direct(0xfeed_face + 0xbeef));
7232
7233
        let result = parse_fde(section, input, |_, _, _| Ok(cie.clone()));
7234
        assert_eq!(result, Ok(fde));
7235
        assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
7236
    }
7237
7238
    #[test]
7239
    fn test_eh_frame_cie_personality_function_relative_bad_context() {
7240
        let instrs = [1, 2, 3, 4];
7241
7242
        let length = Label::new();
7243
        let start = Label::new();
7244
        let end = Label::new();
7245
7246
        let aug_len = Label::new();
7247
        let aug_start = Label::new();
7248
        let aug_end = Label::new();
7249
7250
        let section = Section::with_endian(Endian::Little)
7251
            // Length
7252
            .L32(&length)
7253
            .mark(&start)
7254
            // CIE ID
7255
            .L32(0)
7256
            // Version
7257
            .D8(1)
7258
            // Augmentation
7259
            .append_bytes(b"zP\0")
7260
            // Code alignment factor
7261
            .uleb(1)
7262
            // Data alignment factor
7263
            .sleb(1)
7264
            // Return address register
7265
            .uleb(1)
7266
            // Augmentation data length. This is a uleb, be we rely on the value
7267
            // being less than 2^7 and therefore a valid uleb (can't use Label
7268
            // with uleb).
7269
            .D8(&aug_len)
7270
            .mark(&aug_start)
7271
            // Augmentation data. Personality encoding and then encoded pointer.
7272
            .D8(constants::DW_EH_PE_funcrel.0 | constants::DW_EH_PE_uleb128.0)
7273
            .uleb(1)
7274
            .mark(&aug_end)
7275
            // Initial instructions
7276
            .append_bytes(&instrs)
7277
            .mark(&end);
7278
7279
        length.set_const((&end - &start) as u64);
7280
        aug_len.set_const((&aug_end - &aug_start) as u64);
7281
7282
        let section = section.get_contents().unwrap();
7283
        let section = EhFrame::new(&section, LittleEndian);
7284
7285
        let bases = BaseAddresses::default();
7286
        let mut iter = section.entries(&bases);
7287
        assert_eq!(iter.next(), Err(Error::FuncRelativePointerInBadContext));
7288
    }
7289
7290
    #[test]
7291
    fn register_rule_map_eq() {
7292
        // Different order, but still equal.
7293
        let map1: RegisterRuleMap<usize> = [
7294
            (Register(0), RegisterRule::SameValue),
7295
            (Register(3), RegisterRule::Offset(1)),
7296
        ]
7297
        .iter()
7298
        .collect();
7299
        let map2: RegisterRuleMap<usize> = [
7300
            (Register(3), RegisterRule::Offset(1)),
7301
            (Register(0), RegisterRule::SameValue),
7302
        ]
7303
        .iter()
7304
        .collect();
7305
        assert_eq!(map1, map2);
7306
        assert_eq!(map2, map1);
7307
7308
        // Not equal.
7309
        let map3: RegisterRuleMap<usize> = [
7310
            (Register(0), RegisterRule::SameValue),
7311
            (Register(2), RegisterRule::Offset(1)),
7312
        ]
7313
        .iter()
7314
        .collect();
7315
        let map4: RegisterRuleMap<usize> = [
7316
            (Register(3), RegisterRule::Offset(1)),
7317
            (Register(0), RegisterRule::SameValue),
7318
        ]
7319
        .iter()
7320
        .collect();
7321
        assert!(map3 != map4);
7322
        assert!(map4 != map3);
7323
7324
        // One has undefined explicitly set, other implicitly has undefined.
7325
        let mut map5 = RegisterRuleMap::<usize>::default();
7326
        map5.set(Register(0), RegisterRule::SameValue).unwrap();
7327
        map5.set(Register(0), RegisterRule::Undefined).unwrap();
7328
        let map6 = RegisterRuleMap::<usize>::default();
7329
        assert_eq!(map5, map6);
7330
        assert_eq!(map6, map5);
7331
    }
7332
7333
    #[test]
7334
    fn iter_register_rules() {
7335
        let row = UnwindTableRow::<usize> {
7336
            registers: [
7337
                (Register(0), RegisterRule::SameValue),
7338
                (Register(1), RegisterRule::Offset(1)),
7339
                (Register(2), RegisterRule::ValOffset(2)),
7340
            ]
7341
            .iter()
7342
            .collect(),
7343
            ..Default::default()
7344
        };
7345
7346
        let mut found0 = false;
7347
        let mut found1 = false;
7348
        let mut found2 = false;
7349
7350
        for &(register, ref rule) in row.registers() {
7351
            match register.0 {
7352
                0 => {
7353
                    assert!(!found0);
7354
                    found0 = true;
7355
                    assert_eq!(*rule, RegisterRule::SameValue);
7356
                }
7357
                1 => {
7358
                    assert!(!found1);
7359
                    found1 = true;
7360
                    assert_eq!(*rule, RegisterRule::Offset(1));
7361
                }
7362
                2 => {
7363
                    assert!(!found2);
7364
                    found2 = true;
7365
                    assert_eq!(*rule, RegisterRule::ValOffset(2));
7366
                }
7367
                x => panic!("Unexpected register rule: ({}, {:?})", x, rule),
7368
            }
7369
        }
7370
7371
        assert!(found0);
7372
        assert!(found1);
7373
        assert!(found2);
7374
    }
7375
7376
    #[test]
7377
    #[cfg(target_pointer_width = "64")]
7378
    fn size_of_unwind_ctx() {
7379
        use core::mem;
7380
        let size = mem::size_of::<UnwindContext<usize>>();
7381
        let max_size = 30968;
7382
        if size > max_size {
7383
            assert_eq!(size, max_size);
7384
        }
7385
    }
7386
7387
    #[test]
7388
    #[cfg(target_pointer_width = "64")]
7389
    fn size_of_register_rule_map() {
7390
        use core::mem;
7391
        let size = mem::size_of::<RegisterRuleMap<usize>>();
7392
        let max_size = 6152;
7393
        if size > max_size {
7394
            assert_eq!(size, max_size);
7395
        }
7396
    }
7397
7398
    #[test]
7399
    fn test_parse_pointer_encoding_ok() {
7400
        use crate::endianity::NativeEndian;
7401
        let expected = constants::DW_EH_PE_uleb128 | constants::DW_EH_PE_pcrel;
7402
        let input = [expected.0, 1, 2, 3, 4];
7403
        let input = &mut EndianSlice::new(&input, NativeEndian);
7404
        assert_eq!(parse_pointer_encoding(input), Ok(expected));
7405
        assert_eq!(*input, EndianSlice::new(&[1, 2, 3, 4], NativeEndian));
7406
    }
7407
7408
    #[test]
7409
    fn test_parse_pointer_encoding_bad_encoding() {
7410
        use crate::endianity::NativeEndian;
7411
        let expected =
7412
            constants::DwEhPe((constants::DW_EH_PE_sdata8.0 + 1) | constants::DW_EH_PE_pcrel.0);
7413
        let input = [expected.0, 1, 2, 3, 4];
7414
        let input = &mut EndianSlice::new(&input, NativeEndian);
7415
        assert_eq!(
7416
            Err(Error::UnknownPointerEncoding(expected)),
7417
            parse_pointer_encoding(input)
7418
        );
7419
    }
7420
7421
    #[test]
7422
    fn test_parse_encoded_pointer_absptr() {
7423
        let encoding = constants::DW_EH_PE_absptr;
7424
        let expected_rest = [1, 2, 3, 4];
7425
7426
        let input = Section::with_endian(Endian::Little)
7427
            .L32(0xf00d_f00d)
7428
            .append_bytes(&expected_rest);
7429
        let input = input.get_contents().unwrap();
7430
        let input = EndianSlice::new(&input, LittleEndian);
7431
        let mut rest = input;
7432
7433
        let parameters = PointerEncodingParameters {
7434
            bases: &SectionBaseAddresses::default(),
7435
            func_base: None,
7436
            address_size: 4,
7437
            section: &input,
7438
        };
7439
        assert_eq!(
7440
            parse_encoded_pointer(encoding, &parameters, &mut rest),
7441
            Ok(Pointer::Direct(0xf00d_f00d))
7442
        );
7443
        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7444
    }
7445
7446
    #[test]
7447
    fn test_parse_encoded_pointer_pcrel() {
7448
        let encoding = constants::DW_EH_PE_pcrel;
7449
        let expected_rest = [1, 2, 3, 4];
7450
7451
        let input = Section::with_endian(Endian::Little)
7452
            .append_repeated(0, 0x10)
7453
            .L32(0x1)
7454
            .append_bytes(&expected_rest);
7455
        let input = input.get_contents().unwrap();
7456
        let input = EndianSlice::new(&input, LittleEndian);
7457
        let mut rest = input.range_from(0x10..);
7458
7459
        let parameters = PointerEncodingParameters {
7460
            bases: &BaseAddresses::default().set_eh_frame(0x100).eh_frame,
7461
            func_base: None,
7462
            address_size: 4,
7463
            section: &input,
7464
        };
7465
        assert_eq!(
7466
            parse_encoded_pointer(encoding, &parameters, &mut rest),
7467
            Ok(Pointer::Direct(0x111))
7468
        );
7469
        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7470
    }
7471
7472
    #[test]
7473
    fn test_parse_encoded_pointer_pcrel_undefined() {
7474
        let encoding = constants::DW_EH_PE_pcrel;
7475
7476
        let input = Section::with_endian(Endian::Little).L32(0x1);
7477
        let input = input.get_contents().unwrap();
7478
        let input = EndianSlice::new(&input, LittleEndian);
7479
        let mut rest = input;
7480
7481
        let parameters = PointerEncodingParameters {
7482
            bases: &SectionBaseAddresses::default(),
7483
            func_base: None,
7484
            address_size: 4,
7485
            section: &input,
7486
        };
7487
        assert_eq!(
7488
            parse_encoded_pointer(encoding, &parameters, &mut rest),
7489
            Err(Error::PcRelativePointerButSectionBaseIsUndefined)
7490
        );
7491
    }
7492
7493
    #[test]
7494
    fn test_parse_encoded_pointer_textrel() {
7495
        let encoding = constants::DW_EH_PE_textrel;
7496
        let expected_rest = [1, 2, 3, 4];
7497
7498
        let input = Section::with_endian(Endian::Little)
7499
            .L32(0x1)
7500
            .append_bytes(&expected_rest);
7501
        let input = input.get_contents().unwrap();
7502
        let input = EndianSlice::new(&input, LittleEndian);
7503
        let mut rest = input;
7504
7505
        let parameters = PointerEncodingParameters {
7506
            bases: &BaseAddresses::default().set_text(0x10).eh_frame,
7507
            func_base: None,
7508
            address_size: 4,
7509
            section: &input,
7510
        };
7511
        assert_eq!(
7512
            parse_encoded_pointer(encoding, &parameters, &mut rest),
7513
            Ok(Pointer::Direct(0x11))
7514
        );
7515
        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7516
    }
7517
7518
    #[test]
7519
    fn test_parse_encoded_pointer_textrel_undefined() {
7520
        let encoding = constants::DW_EH_PE_textrel;
7521
7522
        let input = Section::with_endian(Endian::Little).L32(0x1);
7523
        let input = input.get_contents().unwrap();
7524
        let input = EndianSlice::new(&input, LittleEndian);
7525
        let mut rest = input;
7526
7527
        let parameters = PointerEncodingParameters {
7528
            bases: &SectionBaseAddresses::default(),
7529
            func_base: None,
7530
            address_size: 4,
7531
            section: &input,
7532
        };
7533
        assert_eq!(
7534
            parse_encoded_pointer(encoding, &parameters, &mut rest),
7535
            Err(Error::TextRelativePointerButTextBaseIsUndefined)
7536
        );
7537
    }
7538
7539
    #[test]
7540
    fn test_parse_encoded_pointer_datarel() {
7541
        let encoding = constants::DW_EH_PE_datarel;
7542
        let expected_rest = [1, 2, 3, 4];
7543
7544
        let input = Section::with_endian(Endian::Little)
7545
            .L32(0x1)
7546
            .append_bytes(&expected_rest);
7547
        let input = input.get_contents().unwrap();
7548
        let input = EndianSlice::new(&input, LittleEndian);
7549
        let mut rest = input;
7550
7551
        let parameters = PointerEncodingParameters {
7552
            bases: &BaseAddresses::default().set_got(0x10).eh_frame,
7553
            func_base: None,
7554
            address_size: 4,
7555
            section: &input,
7556
        };
7557
        assert_eq!(
7558
            parse_encoded_pointer(encoding, &parameters, &mut rest),
7559
            Ok(Pointer::Direct(0x11))
7560
        );
7561
        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7562
    }
7563
7564
    #[test]
7565
    fn test_parse_encoded_pointer_datarel_undefined() {
7566
        let encoding = constants::DW_EH_PE_datarel;
7567
7568
        let input = Section::with_endian(Endian::Little).L32(0x1);
7569
        let input = input.get_contents().unwrap();
7570
        let input = EndianSlice::new(&input, LittleEndian);
7571
        let mut rest = input;
7572
7573
        let parameters = PointerEncodingParameters {
7574
            bases: &SectionBaseAddresses::default(),
7575
            func_base: None,
7576
            address_size: 4,
7577
            section: &input,
7578
        };
7579
        assert_eq!(
7580
            parse_encoded_pointer(encoding, &parameters, &mut rest),
7581
            Err(Error::DataRelativePointerButDataBaseIsUndefined)
7582
        );
7583
    }
7584
7585
    #[test]
7586
    fn test_parse_encoded_pointer_funcrel() {
7587
        let encoding = constants::DW_EH_PE_funcrel;
7588
        let expected_rest = [1, 2, 3, 4];
7589
7590
        let input = Section::with_endian(Endian::Little)
7591
            .L32(0x1)
7592
            .append_bytes(&expected_rest);
7593
        let input = input.get_contents().unwrap();
7594
        let input = EndianSlice::new(&input, LittleEndian);
7595
        let mut rest = input;
7596
7597
        let parameters = PointerEncodingParameters {
7598
            bases: &SectionBaseAddresses::default(),
7599
            func_base: Some(0x10),
7600
            address_size: 4,
7601
            section: &input,
7602
        };
7603
        assert_eq!(
7604
            parse_encoded_pointer(encoding, &parameters, &mut rest),
7605
            Ok(Pointer::Direct(0x11))
7606
        );
7607
        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7608
    }
7609
7610
    #[test]
7611
    fn test_parse_encoded_pointer_funcrel_undefined() {
7612
        let encoding = constants::DW_EH_PE_funcrel;
7613
7614
        let input = Section::with_endian(Endian::Little).L32(0x1);
7615
        let input = input.get_contents().unwrap();
7616
        let input = EndianSlice::new(&input, LittleEndian);
7617
        let mut rest = input;
7618
7619
        let parameters = PointerEncodingParameters {
7620
            bases: &SectionBaseAddresses::default(),
7621
            func_base: None,
7622
            address_size: 4,
7623
            section: &input,
7624
        };
7625
        assert_eq!(
7626
            parse_encoded_pointer(encoding, &parameters, &mut rest),
7627
            Err(Error::FuncRelativePointerInBadContext)
7628
        );
7629
    }
7630
7631
    #[test]
7632
    fn test_parse_encoded_pointer_uleb128() {
7633
        let encoding = constants::DW_EH_PE_absptr | constants::DW_EH_PE_uleb128;
7634
        let expected_rest = [1, 2, 3, 4];
7635
7636
        let input = Section::with_endian(Endian::Little)
7637
            .uleb(0x12_3456)
7638
            .append_bytes(&expected_rest);
7639
        let input = input.get_contents().unwrap();
7640
        let input = EndianSlice::new(&input, LittleEndian);
7641
        let mut rest = input;
7642
7643
        let parameters = PointerEncodingParameters {
7644
            bases: &SectionBaseAddresses::default(),
7645
            func_base: None,
7646
            address_size: 4,
7647
            section: &input,
7648
        };
7649
        assert_eq!(
7650
            parse_encoded_pointer(encoding, &parameters, &mut rest),
7651
            Ok(Pointer::Direct(0x12_3456))
7652
        );
7653
        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7654
    }
7655
7656
    #[test]
7657
    fn test_parse_encoded_pointer_udata2() {
7658
        let encoding = constants::DW_EH_PE_absptr | constants::DW_EH_PE_udata2;
7659
        let expected_rest = [1, 2, 3, 4];
7660
7661
        let input = Section::with_endian(Endian::Little)
7662
            .L16(0x1234)
7663
            .append_bytes(&expected_rest);
7664
        let input = input.get_contents().unwrap();
7665
        let input = EndianSlice::new(&input, LittleEndian);
7666
        let mut rest = input;
7667
7668
        let parameters = PointerEncodingParameters {
7669
            bases: &SectionBaseAddresses::default(),
7670
            func_base: None,
7671
            address_size: 4,
7672
            section: &input,
7673
        };
7674
        assert_eq!(
7675
            parse_encoded_pointer(encoding, &parameters, &mut rest),
7676
            Ok(Pointer::Direct(0x1234))
7677
        );
7678
        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7679
    }
7680
7681
    #[test]
7682
    fn test_parse_encoded_pointer_udata4() {
7683
        let encoding = constants::DW_EH_PE_absptr | constants::DW_EH_PE_udata4;
7684
        let expected_rest = [1, 2, 3, 4];
7685
7686
        let input = Section::with_endian(Endian::Little)
7687
            .L32(0x1234_5678)
7688
            .append_bytes(&expected_rest);
7689
        let input = input.get_contents().unwrap();
7690
        let input = EndianSlice::new(&input, LittleEndian);
7691
        let mut rest = input;
7692
7693
        let parameters = PointerEncodingParameters {
7694
            bases: &SectionBaseAddresses::default(),
7695
            func_base: None,
7696
            address_size: 4,
7697
            section: &input,
7698
        };
7699
        assert_eq!(
7700
            parse_encoded_pointer(encoding, &parameters, &mut rest),
7701
            Ok(Pointer::Direct(0x1234_5678))
7702
        );
7703
        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7704
    }
7705
7706
    #[test]
7707
    fn test_parse_encoded_pointer_udata8() {
7708
        let encoding = constants::DW_EH_PE_absptr | constants::DW_EH_PE_udata8;
7709
        let expected_rest = [1, 2, 3, 4];
7710
7711
        let input = Section::with_endian(Endian::Little)
7712
            .L64(0x1234_5678_1234_5678)
7713
            .append_bytes(&expected_rest);
7714
        let input = input.get_contents().unwrap();
7715
        let input = EndianSlice::new(&input, LittleEndian);
7716
        let mut rest = input;
7717
7718
        let parameters = PointerEncodingParameters {
7719
            bases: &SectionBaseAddresses::default(),
7720
            func_base: None,
7721
            address_size: 8,
7722
            section: &input,
7723
        };
7724
        assert_eq!(
7725
            parse_encoded_pointer(encoding, &parameters, &mut rest),
7726
            Ok(Pointer::Direct(0x1234_5678_1234_5678))
7727
        );
7728
        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7729
    }
7730
7731
    #[test]
7732
    fn test_parse_encoded_pointer_sleb128() {
7733
        let encoding = constants::DW_EH_PE_textrel | constants::DW_EH_PE_sleb128;
7734
        let expected_rest = [1, 2, 3, 4];
7735
7736
        let input = Section::with_endian(Endian::Little)
7737
            .sleb(-0x1111)
7738
            .append_bytes(&expected_rest);
7739
        let input = input.get_contents().unwrap();
7740
        let input = EndianSlice::new(&input, LittleEndian);
7741
        let mut rest = input;
7742
7743
        let parameters = PointerEncodingParameters {
7744
            bases: &BaseAddresses::default().set_text(0x1111_1111).eh_frame,
7745
            func_base: None,
7746
            address_size: 4,
7747
            section: &input,
7748
        };
7749
        assert_eq!(
7750
            parse_encoded_pointer(encoding, &parameters, &mut rest),
7751
            Ok(Pointer::Direct(0x1111_0000))
7752
        );
7753
        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7754
    }
7755
7756
    #[test]
7757
    fn test_parse_encoded_pointer_sdata2() {
7758
        let encoding = constants::DW_EH_PE_absptr | constants::DW_EH_PE_sdata2;
7759
        let expected_rest = [1, 2, 3, 4];
7760
        let expected = 0x111_i16;
7761
7762
        let input = Section::with_endian(Endian::Little)
7763
            .L16(expected as u16)
7764
            .append_bytes(&expected_rest);
7765
        let input = input.get_contents().unwrap();
7766
        let input = EndianSlice::new(&input, LittleEndian);
7767
        let mut rest = input;
7768
7769
        let parameters = PointerEncodingParameters {
7770
            bases: &SectionBaseAddresses::default(),
7771
            func_base: None,
7772
            address_size: 4,
7773
            section: &input,
7774
        };
7775
        assert_eq!(
7776
            parse_encoded_pointer(encoding, &parameters, &mut rest),
7777
            Ok(Pointer::Direct(expected as u64))
7778
        );
7779
        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7780
    }
7781
7782
    #[test]
7783
    fn test_parse_encoded_pointer_sdata4() {
7784
        let encoding = constants::DW_EH_PE_absptr | constants::DW_EH_PE_sdata4;
7785
        let expected_rest = [1, 2, 3, 4];
7786
        let expected = 0x111_1111_i32;
7787
7788
        let input = Section::with_endian(Endian::Little)
7789
            .L32(expected as u32)
7790
            .append_bytes(&expected_rest);
7791
        let input = input.get_contents().unwrap();
7792
        let input = EndianSlice::new(&input, LittleEndian);
7793
        let mut rest = input;
7794
7795
        let parameters = PointerEncodingParameters {
7796
            bases: &SectionBaseAddresses::default(),
7797
            func_base: None,
7798
            address_size: 4,
7799
            section: &input,
7800
        };
7801
        assert_eq!(
7802
            parse_encoded_pointer(encoding, &parameters, &mut rest),
7803
            Ok(Pointer::Direct(expected as u64))
7804
        );
7805
        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7806
    }
7807
7808
    #[test]
7809
    fn test_parse_encoded_pointer_sdata8() {
7810
        let encoding = constants::DW_EH_PE_absptr | constants::DW_EH_PE_sdata8;
7811
        let expected_rest = [1, 2, 3, 4];
7812
        let expected = -0x11_1111_1222_2222_i64;
7813
7814
        let input = Section::with_endian(Endian::Little)
7815
            .L64(expected as u64)
7816
            .append_bytes(&expected_rest);
7817
        let input = input.get_contents().unwrap();
7818
        let input = EndianSlice::new(&input, LittleEndian);
7819
        let mut rest = input;
7820
7821
        let parameters = PointerEncodingParameters {
7822
            bases: &SectionBaseAddresses::default(),
7823
            func_base: None,
7824
            address_size: 8,
7825
            section: &input,
7826
        };
7827
        assert_eq!(
7828
            parse_encoded_pointer(encoding, &parameters, &mut rest),
7829
            Ok(Pointer::Direct(expected as u64))
7830
        );
7831
        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7832
    }
7833
7834
    #[test]
7835
    fn test_parse_encoded_pointer_omit() {
7836
        let encoding = constants::DW_EH_PE_omit;
7837
7838
        let input = Section::with_endian(Endian::Little).L32(0x1);
7839
        let input = input.get_contents().unwrap();
7840
        let input = EndianSlice::new(&input, LittleEndian);
7841
        let mut rest = input;
7842
7843
        let parameters = PointerEncodingParameters {
7844
            bases: &SectionBaseAddresses::default(),
7845
            func_base: None,
7846
            address_size: 4,
7847
            section: &input,
7848
        };
7849
        assert_eq!(
7850
            parse_encoded_pointer(encoding, &parameters, &mut rest),
7851
            Err(Error::CannotParseOmitPointerEncoding)
7852
        );
7853
        assert_eq!(rest, input);
7854
    }
7855
7856
    #[test]
7857
    fn test_parse_encoded_pointer_bad_encoding() {
7858
        let encoding = constants::DwEhPe(constants::DW_EH_PE_sdata8.0 + 1);
7859
7860
        let input = Section::with_endian(Endian::Little).L32(0x1);
7861
        let input = input.get_contents().unwrap();
7862
        let input = EndianSlice::new(&input, LittleEndian);
7863
        let mut rest = input;
7864
7865
        let parameters = PointerEncodingParameters {
7866
            bases: &SectionBaseAddresses::default(),
7867
            func_base: None,
7868
            address_size: 4,
7869
            section: &input,
7870
        };
7871
        assert_eq!(
7872
            parse_encoded_pointer(encoding, &parameters, &mut rest),
7873
            Err(Error::UnknownPointerEncoding(encoding))
7874
        );
7875
    }
7876
7877
    #[test]
7878
    fn test_parse_encoded_pointer_aligned() {
7879
        // FIXME: support this encoding!
7880
7881
        let encoding = constants::DW_EH_PE_aligned;
7882
7883
        let input = Section::with_endian(Endian::Little).L32(0x1);
7884
        let input = input.get_contents().unwrap();
7885
        let input = EndianSlice::new(&input, LittleEndian);
7886
        let mut rest = input;
7887
7888
        let parameters = PointerEncodingParameters {
7889
            bases: &SectionBaseAddresses::default(),
7890
            func_base: None,
7891
            address_size: 4,
7892
            section: &input,
7893
        };
7894
        assert_eq!(
7895
            parse_encoded_pointer(encoding, &parameters, &mut rest),
7896
            Err(Error::UnsupportedPointerEncoding)
7897
        );
7898
    }
7899
7900
    #[test]
7901
    fn test_parse_encoded_pointer_indirect() {
7902
        let expected_rest = [1, 2, 3, 4];
7903
        let encoding = constants::DW_EH_PE_indirect;
7904
7905
        let input = Section::with_endian(Endian::Little)
7906
            .L32(0x1234_5678)
7907
            .append_bytes(&expected_rest);
7908
        let input = input.get_contents().unwrap();
7909
        let input = EndianSlice::new(&input, LittleEndian);
7910
        let mut rest = input;
7911
7912
        let parameters = PointerEncodingParameters {
7913
            bases: &SectionBaseAddresses::default(),
7914
            func_base: None,
7915
            address_size: 4,
7916
            section: &input,
7917
        };
7918
        assert_eq!(
7919
            parse_encoded_pointer(encoding, &parameters, &mut rest),
7920
            Ok(Pointer::Indirect(0x1234_5678))
7921
        );
7922
        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7923
    }
7924
7925
    #[test]
7926
    fn test_unwind_context_reuse() {
7927
        fn unwind_one(ctx: &mut UnwindContext<usize>, data: &[u8]) {
7928
            let debug_frame = DebugFrame::new(data, NativeEndian);
7929
            let bases = Default::default();
7930
            let result = debug_frame.unwind_info_for_address(
7931
                &bases,
7932
                ctx,
7933
                0xbadb_ad99,
7934
                DebugFrame::cie_from_offset,
7935
            );
7936
            assert!(result.is_err());
7937
            assert_eq!(result.unwrap_err(), Error::NoUnwindInfoForAddress);
7938
        }
7939
7940
        // Use the same context for two different data lifetimes.
7941
        let mut ctx: UnwindContext<usize> = UnwindContext::new();
7942
        {
7943
            let data1 = vec![];
7944
            unwind_one(&mut ctx, &data1);
7945
        }
7946
        {
7947
            let data2 = vec![];
7948
            unwind_one(&mut ctx, &data2);
7949
        }
7950
    }
7951
}