gimli/read/
cfi.rs

1#[cfg(feature = "read")]
2use alloc::boxed::Box;
3
4use core::cmp::Ordering;
5use core::fmt::{self, Debug};
6use core::iter::FromIterator;
7use core::mem;
8use core::num::Wrapping;
9
10use super::util::{ArrayLike, ArrayVec};
11use crate::common::{
12    DebugFrameOffset, EhFrameOffset, Encoding, Format, Register, SectionId, Vendor,
13};
14use crate::constants::{self, DwEhPe};
15use crate::endianity::Endianity;
16use 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)]
36pub struct DebugFrame<R: Reader> {
37    section: R,
38    address_size: u8,
39    vendor: Vendor,
40}
41
42impl<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    pub fn set_address_size(&mut self, address_size: u8) {
48        self.address_size = address_size
49    }
50
51    /// Set the vendor extensions to use.
52    ///
53    /// This defaults to `Vendor::Default`.
54    pub fn set_vendor(&mut self, vendor: Vendor) {
55        self.vendor = vendor;
56    }
57}
58
59impl<'input, Endian> DebugFrame<EndianSlice<'input, Endian>>
60where
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    pub fn new(section: &'input [u8], endian: Endian) -> Self {
79        Self::from(EndianSlice::new(section, endian))
80    }
81}
82
83impl<R: Reader> Section<R> for DebugFrame<R> {
84    fn id() -> SectionId {
85        SectionId::DebugFrame
86    }
87
88    fn reader(&self) -> &R {
89        &self.section
90    }
91}
92
93impl<R: Reader> From<R> for DebugFrame<R> {
94    fn from(section: R) -> Self {
95        // Default to native word size.
96        DebugFrame {
97            section,
98            address_size: mem::size_of::<usize>() as u8,
99            vendor: Vendor::Default,
100        }
101    }
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)]
109pub struct EhFrameHdr<R: Reader>(R);
110
111/// `ParsedEhFrameHdr` contains the parsed information from the `.eh_frame_hdr` section.
112#[derive(Clone, Debug)]
113pub 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
123impl<'input, Endian> EhFrameHdr<EndianSlice<'input, Endian>>
124where
125    Endian: Endianity,
126{
127    /// Constructs a new `EhFrameHdr` instance from the data in the `.eh_frame_hdr` section.
128    pub fn new(section: &'input [u8], endian: Endian) -> Self {
129        Self::from(EndianSlice::new(section, endian))
130    }
131}
132
133impl<R: Reader> EhFrameHdr<R> {
134    /// Parses this `EhFrameHdr` to a `ParsedEhFrameHdr`.
135    pub fn parse(&self, bases: &BaseAddresses, address_size: u8) -> Result<ParsedEhFrameHdr<R>> {
136        let mut reader = self.0.clone();
137        let version = reader.read_u8()?;
138        if version != 1 {
139            return Err(Error::UnknownVersion(u64::from(version)));
140        }
141
142        let eh_frame_ptr_enc = parse_pointer_encoding(&mut reader)?;
143        let fde_count_enc = parse_pointer_encoding(&mut reader)?;
144        let table_enc = parse_pointer_encoding(&mut reader)?;
145
146        let parameters = PointerEncodingParameters {
147            bases: &bases.eh_frame_hdr,
148            func_base: None,
149            address_size,
150            section: &self.0,
151        };
152
153        // Omitting this pointer is not valid (defeats the purpose of .eh_frame_hdr entirely)
154        if eh_frame_ptr_enc == constants::DW_EH_PE_omit {
155            return Err(Error::CannotParseOmitPointerEncoding);
156        }
157        let eh_frame_ptr = parse_encoded_pointer(eh_frame_ptr_enc, &parameters, &mut reader)?;
158
159        let fde_count;
160        if fde_count_enc == constants::DW_EH_PE_omit || table_enc == constants::DW_EH_PE_omit {
161            fde_count = 0
162        } else {
163            if fde_count_enc != fde_count_enc.format() {
164                return Err(Error::UnsupportedPointerEncoding);
165            }
166            fde_count = parse_encoded_value(fde_count_enc, &parameters, &mut reader)?;
167        }
168
169        Ok(ParsedEhFrameHdr {
170            address_size,
171            section: self.0.clone(),
172
173            eh_frame_ptr,
174            fde_count,
175            table_enc,
176            table: reader,
177        })
178    }
179}
180
181impl<R: Reader> Section<R> for EhFrameHdr<R> {
182    fn id() -> SectionId {
183        SectionId::EhFrameHdr
184    }
185
186    fn reader(&self) -> &R {
187        &self.0
188    }
189}
190
191impl<R: Reader> From<R> for EhFrameHdr<R> {
192    fn from(section: R) -> Self {
193        EhFrameHdr(section)
194    }
195}
196
197impl<R: Reader> ParsedEhFrameHdr<R> {
198    /// Returns the address of the binary's `.eh_frame` section.
199    pub fn eh_frame_ptr(&self) -> Pointer {
200        self.eh_frame_ptr
201    }
202
203    /// Retrieves the CFI binary search table, if there is one.
204    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        if self.fde_count == 0 {
215            None
216        } else {
217            Some(EhHdrTable { hdr: self })
218        }
219    }
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)]
229pub struct EhHdrTableIter<'a, 'bases, R: Reader> {
230    hdr: &'a ParsedEhFrameHdr<R>,
231    table: R,
232    bases: &'bases BaseAddresses,
233    remain: u64,
234}
235
236impl<'a, 'bases, R: Reader> EhHdrTableIter<'a, 'bases, R> {
237    /// Yield the next entry in the `EhHdrTableIter`.
238    pub fn next(&mut self) -> Result<Option<(Pointer, Pointer)>> {
239        if self.remain == 0 {
240            return Ok(None);
241        }
242
243        let parameters = PointerEncodingParameters {
244            bases: &self.bases.eh_frame_hdr,
245            func_base: None,
246            address_size: self.hdr.address_size,
247            section: &self.hdr.section,
248        };
249
250        self.remain -= 1;
251        let from = parse_encoded_pointer(self.hdr.table_enc, &parameters, &mut self.table)?;
252        let to = parse_encoded_pointer(self.hdr.table_enc, &parameters, &mut self.table)?;
253        Ok(Some((from, to)))
254    }
255    /// Yield the nth entry in the `EhHdrTableIter`
256    pub fn nth(&mut self, n: usize) -> Result<Option<(Pointer, Pointer)>> {
257        use core::convert::TryFrom;
258        let size = match self.hdr.table_enc.format() {
259            constants::DW_EH_PE_uleb128 | constants::DW_EH_PE_sleb128 => {
260                return Err(Error::VariableLengthSearchTable);
261            }
262            constants::DW_EH_PE_sdata2 | constants::DW_EH_PE_udata2 => 2,
263            constants::DW_EH_PE_sdata4 | constants::DW_EH_PE_udata4 => 4,
264            constants::DW_EH_PE_sdata8 | constants::DW_EH_PE_udata8 => 8,
265            _ => return Err(Error::UnknownPointerEncoding(self.hdr.table_enc)),
266        };
267
268        let row_size = size * 2;
269        let n = u64::try_from(n).map_err(|_| Error::UnsupportedOffset)?;
270        self.remain = self.remain.saturating_sub(n);
271        self.table.skip(R::Offset::from_u64(n * row_size)?)?;
272        self.next()
273    }
274}
275
276#[cfg(feature = "fallible-iterator")]
277impl<'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)]
299pub struct EhHdrTable<'a, R: Reader> {
300    hdr: &'a ParsedEhFrameHdr<R>,
301}
302
303impl<'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    pub fn iter<'bases>(&self, bases: &'bases BaseAddresses) -> EhHdrTableIter<'_, 'bases, R> {
311        EhHdrTableIter {
312            hdr: self.hdr,
313            bases,
314            remain: self.hdr.fde_count,
315            table: self.hdr.table.clone(),
316        }
317    }
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    pub fn lookup(&self, address: u64, bases: &BaseAddresses) -> Result<Pointer> {
325        let size = match self.hdr.table_enc.format() {
326            constants::DW_EH_PE_uleb128 | constants::DW_EH_PE_sleb128 => {
327                return Err(Error::VariableLengthSearchTable);
328            }
329            constants::DW_EH_PE_sdata2 | constants::DW_EH_PE_udata2 => 2,
330            constants::DW_EH_PE_sdata4 | constants::DW_EH_PE_udata4 => 4,
331            constants::DW_EH_PE_sdata8 | constants::DW_EH_PE_udata8 => 8,
332            _ => return Err(Error::UnknownPointerEncoding(self.hdr.table_enc)),
333        };
334
335        let row_size = size * 2;
336
337        let mut len = self.hdr.fde_count;
338
339        let mut reader = self.hdr.table.clone();
340
341        let parameters = PointerEncodingParameters {
342            bases: &bases.eh_frame_hdr,
343            func_base: None,
344            address_size: self.hdr.address_size,
345            section: &self.hdr.section,
346        };
347
348        while len > 1 {
349            let head = reader.split(R::Offset::from_u64((len / 2) * row_size)?)?;
350            let tail = reader.clone();
351
352            let pivot =
353                parse_encoded_pointer(self.hdr.table_enc, &parameters, &mut reader)?.direct()?;
354
355            match pivot.cmp(&address) {
356                Ordering::Equal => {
357                    reader = tail;
358                    break;
359                }
360                Ordering::Less => {
361                    reader = tail;
362                    len = len - (len / 2);
363                }
364                Ordering::Greater => {
365                    reader = head;
366                    len /= 2;
367                }
368            }
369        }
370
371        reader.skip(R::Offset::from_u64(size)?)?;
372
373        parse_encoded_pointer(self.hdr.table_enc, &parameters, &mut reader)
374    }
375
376    /// Convert a `Pointer` to a section offset.
377    ///
378    /// This does not support indirect pointers.
379    pub fn pointer_to_offset(&self, ptr: Pointer) -> Result<EhFrameOffset<R::Offset>> {
380        let ptr = ptr.direct()?;
381        let eh_frame_ptr = self.hdr.eh_frame_ptr().direct()?;
382
383        // Calculate the offset in the EhFrame section
384        R::Offset::from_u64(ptr - eh_frame_ptr).map(EhFrameOffset)
385    }
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    pub fn fde_for_address<F>(
408        &self,
409        frame: &EhFrame<R>,
410        bases: &BaseAddresses,
411        address: u64,
412        get_cie: F,
413    ) -> Result<FrameDescriptionEntry<R>>
414    where
415        F: FnMut(
416            &EhFrame<R>,
417            &BaseAddresses,
418            EhFrameOffset<R::Offset>,
419        ) -> Result<CommonInformationEntry<R>>,
420    {
421        let fdeptr = self.lookup(address, bases)?;
422        let offset = self.pointer_to_offset(fdeptr)?;
423        let entry = frame.fde_from_offset(bases, offset, get_cie)?;
424        if entry.contains(address) {
425            Ok(entry)
426        } else {
427            Err(Error::NoUnwindInfoForAddress)
428        }
429    }
430
431    #[inline]
432    #[doc(hidden)]
433    #[deprecated(note = "Method renamed to fde_for_address; use that instead.")]
434    pub fn lookup_and_parse<F>(
435        &self,
436        address: u64,
437        bases: &BaseAddresses,
438        frame: EhFrame<R>,
439        get_cie: F,
440    ) -> Result<FrameDescriptionEntry<R>>
441    where
442        F: FnMut(
443            &EhFrame<R>,
444            &BaseAddresses,
445            EhFrameOffset<R::Offset>,
446        ) -> Result<CommonInformationEntry<R>>,
447    {
448        self.fde_for_address(&frame, bases, address, get_cie)
449    }
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    pub fn unwind_info_for_address<'ctx, F, S>(
457        &self,
458        frame: &EhFrame<R>,
459        bases: &BaseAddresses,
460        ctx: &'ctx mut UnwindContext<R::Offset, S>,
461        address: u64,
462        get_cie: F,
463    ) -> Result<&'ctx UnwindTableRow<R::Offset, S>>
464    where
465        F: FnMut(
466            &EhFrame<R>,
467            &BaseAddresses,
468            EhFrameOffset<R::Offset>,
469        ) -> Result<CommonInformationEntry<R>>,
470        S: UnwindContextStorage<R::Offset>,
471    {
472        let fde = self.fde_for_address(frame, bases, address, get_cie)?;
473        fde.unwind_info_for_address(frame, bases, ctx, address)
474    }
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)]
488pub struct EhFrame<R: Reader> {
489    section: R,
490    address_size: u8,
491    vendor: Vendor,
492}
493
494impl<R: Reader> EhFrame<R> {
495    /// Set the size of a target address in bytes.
496    ///
497    /// This defaults to the native word size.
498    pub fn set_address_size(&mut self, address_size: u8) {
499        self.address_size = address_size
500    }
501
502    /// Set the vendor extensions to use.
503    ///
504    /// This defaults to `Vendor::Default`.
505    pub fn set_vendor(&mut self, vendor: Vendor) {
506        self.vendor = vendor;
507    }
508}
509
510impl<'input, Endian> EhFrame<EndianSlice<'input, Endian>>
511where
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    pub fn new(section: &'input [u8], endian: Endian) -> Self {
530        Self::from(EndianSlice::new(section, endian))
531    }
532}
533
534impl<R: Reader> Section<R> for EhFrame<R> {
535    fn id() -> SectionId {
536        SectionId::EhFrame
537    }
538
539    fn reader(&self) -> &R {
540        &self.section
541    }
542}
543
544impl<R: Reader> From<R> for EhFrame<R> {
545    fn from(section: R) -> Self {
546        // Default to native word size.
547        EhFrame {
548            section,
549            address_size: mem::size_of::<usize>() as u8,
550            vendor: Vendor::Default,
551        }
552    }
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)]
560pub enum CieOffsetEncoding {
561    U32,
562    U64,
563}
564
565/// An offset into an `UnwindSection`.
566//
567// Needed to avoid conflicting implementations of `Into<T>`.
568pub trait UnwindOffset<T = usize>: Copy + Debug + Eq + From<T>
569where
570    T: ReaderOffset,
571{
572    /// Convert an `UnwindOffset<T>` into a `T`.
573    fn into(self) -> T;
574}
575
576impl<T> UnwindOffset<T> for DebugFrameOffset<T>
577where
578    T: ReaderOffset,
579{
580    #[inline]
581    fn into(self) -> T {
582        self.0
583    }
584}
585
586impl<T> UnwindOffset<T> for EhFrameOffset<T>
587where
588    T: ReaderOffset,
589{
590    #[inline]
591    fn into(self) -> T {
592        self.0
593    }
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)]
600pub 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.
635pub 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    fn entries<'bases>(&self, bases: &'bases BaseAddresses) -> CfiEntriesIter<'bases, Self, R> {
646        CfiEntriesIter {
647            section: self.clone(),
648            bases,
649            input: self.section().clone(),
650        }
651    }
652
653    /// Parse the `CommonInformationEntry` at the given offset.
654    fn cie_from_offset(
655        &self,
656        bases: &BaseAddresses,
657        offset: Self::Offset,
658    ) -> Result<CommonInformationEntry<R>> {
659        let offset = UnwindOffset::into(offset);
660        let input = &mut self.section().clone();
661        input.skip(offset)?;
662        CommonInformationEntry::parse(bases, self, input)
663    }
664
665    /// Parse the `PartialFrameDescriptionEntry` at the given offset.
666    fn partial_fde_from_offset<'bases>(
667        &self,
668        bases: &'bases BaseAddresses,
669        offset: Self::Offset,
670    ) -> Result<PartialFrameDescriptionEntry<'bases, Self, R>> {
671        let offset = UnwindOffset::into(offset);
672        let input = &mut self.section().clone();
673        input.skip(offset)?;
674        PartialFrameDescriptionEntry::parse_partial(self, bases, input)
675    }
676
677    /// Parse the `FrameDescriptionEntry` at the given offset.
678    fn fde_from_offset<F>(
679        &self,
680        bases: &BaseAddresses,
681        offset: Self::Offset,
682        get_cie: F,
683    ) -> Result<FrameDescriptionEntry<R>>
684    where
685        F: FnMut(&Self, &BaseAddresses, Self::Offset) -> Result<CommonInformationEntry<R>>,
686    {
687        let partial = self.partial_fde_from_offset(bases, offset)?;
688        partial.parse(get_cie)
689    }
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    fn fde_for_address<F>(
703        &self,
704        bases: &BaseAddresses,
705        address: u64,
706        mut get_cie: F,
707    ) -> Result<FrameDescriptionEntry<R>>
708    where
709        F: FnMut(&Self, &BaseAddresses, Self::Offset) -> Result<CommonInformationEntry<R>>,
710    {
711        let mut entries = self.entries(bases);
712        while let Some(entry) = entries.next()? {
713            match entry {
714                CieOrFde::Cie(_) => {}
715                CieOrFde::Fde(partial) => {
716                    let fde = partial.parse(&mut get_cie)?;
717                    if fde.contains(address) {
718                        return Ok(fde);
719                    }
720                }
721            }
722        }
723        Err(Error::NoUnwindInfoForAddress)
724    }
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    fn unwind_info_for_address<'ctx, F, S>(
773        &self,
774        bases: &BaseAddresses,
775        ctx: &'ctx mut UnwindContext<R::Offset, S>,
776        address: u64,
777        get_cie: F,
778    ) -> Result<&'ctx UnwindTableRow<R::Offset, S>>
779    where
780        F: FnMut(&Self, &BaseAddresses, Self::Offset) -> Result<CommonInformationEntry<R>>,
781        S: UnwindContextStorage<R::Offset>,
782    {
783        let fde = self.fde_for_address(bases, address, get_cie)?;
784        fde.unwind_info_for_address(self, bases, ctx, address)
785    }
786}
787
788impl<R: Reader> _UnwindSectionPrivate<R> for DebugFrame<R> {
789    fn section(&self) -> &R {
790        &self.section
791    }
792
793    fn has_zero_terminator() -> bool {
794        false
795    }
796
797    fn is_cie(format: Format, id: u64) -> bool {
798        match format {
799            Format::Dwarf32 => id == 0xffff_ffff,
800            Format::Dwarf64 => id == 0xffff_ffff_ffff_ffff,
801        }
802    }
803
804    fn cie_offset_encoding(format: Format) -> CieOffsetEncoding {
805        match format {
806            Format::Dwarf32 => CieOffsetEncoding::U32,
807            Format::Dwarf64 => CieOffsetEncoding::U64,
808        }
809    }
810
811    fn resolve_cie_offset(&self, _: R::Offset, offset: R::Offset) -> Option<R::Offset> {
812        Some(offset)
813    }
814
815    fn has_address_and_segment_sizes(version: u8) -> bool {
816        version == 4
817    }
818
819    fn address_size(&self) -> u8 {
820        self.address_size
821    }
822
823    fn vendor(&self) -> Vendor {
824        self.vendor
825    }
826}
827
828impl<R: Reader> UnwindSection<R> for DebugFrame<R> {
829    type Offset = DebugFrameOffset<R::Offset>;
830}
831
832impl<R: Reader> _UnwindSectionPrivate<R> for EhFrame<R> {
833    fn section(&self) -> &R {
834        &self.section
835    }
836
837    fn has_zero_terminator() -> bool {
838        true
839    }
840
841    fn is_cie(_: Format, id: u64) -> bool {
842        id == 0
843    }
844
845    fn cie_offset_encoding(_format: Format) -> CieOffsetEncoding {
846        // `.eh_frame` offsets are always 4 bytes, regardless of the DWARF
847        // format.
848        CieOffsetEncoding::U32
849    }
850
851    fn resolve_cie_offset(&self, base: R::Offset, offset: R::Offset) -> Option<R::Offset> {
852        base.checked_sub(offset)
853    }
854
855    fn has_address_and_segment_sizes(_version: u8) -> bool {
856        false
857    }
858
859    fn address_size(&self) -> u8 {
860        self.address_size
861    }
862
863    fn vendor(&self) -> Vendor {
864        self.vendor
865    }
866}
867
868impl<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)]
895pub 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)]
908pub 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
926impl BaseAddresses {
927    /// Set the `.eh_frame_hdr` section base address.
928    #[inline]
929    pub fn set_eh_frame_hdr(mut self, addr: u64) -> Self {
930        self.eh_frame_hdr.section = Some(addr);
931        self.eh_frame_hdr.data = Some(addr);
932        self
933    }
934
935    /// Set the `.eh_frame` section base address.
936    #[inline]
937    pub fn set_eh_frame(mut self, addr: u64) -> Self {
938        self.eh_frame.section = Some(addr);
939        self
940    }
941
942    /// Set the `.text` section base address.
943    #[inline]
944    pub fn set_text(mut self, addr: u64) -> Self {
945        self.eh_frame_hdr.text = Some(addr);
946        self.eh_frame.text = Some(addr);
947        self
948    }
949
950    /// Set the `.got` section base address.
951    #[inline]
952    pub fn set_got(mut self, addr: u64) -> Self {
953        self.eh_frame.data = Some(addr);
954        self
955    }
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)]
998pub struct CfiEntriesIter<'bases, Section, R>
999where
1000    R: Reader,
1001    Section: UnwindSection<R>,
1002{
1003    section: Section,
1004    bases: &'bases BaseAddresses,
1005    input: R,
1006}
1007
1008impl<'bases, Section, R> CfiEntriesIter<'bases, Section, R>
1009where
1010    R: Reader,
1011    Section: UnwindSection<R>,
1012{
1013    /// Advance the iterator to the next entry.
1014    pub fn next(&mut self) -> Result<Option<CieOrFde<'bases, Section, R>>> {
1015        loop {
1016            if self.input.is_empty() {
1017                return Ok(None);
1018            }
1019
1020            match parse_cfi_entry(self.bases, &self.section, &mut self.input) {
1021                Ok(Some(entry)) => return Ok(Some(entry)),
1022                Err(e) => {
1023                    self.input.empty();
1024                    return Err(e);
1025                }
1026                Ok(None) => {
1027                    if Section::has_zero_terminator() {
1028                        self.input.empty();
1029                        return Ok(None);
1030                    }
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                    continue;
1037                }
1038            }
1039        }
1040    }
1041}
1042
1043#[cfg(feature = "fallible-iterator")]
1044impl<'bases, Section, R> fallible_iterator::FallibleIterator for CfiEntriesIter<'bases, Section, R>
1045where
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)]
1059pub enum CieOrFde<'bases, Section, R>
1060where
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
1072fn parse_cfi_entry<'bases, Section, R>(
1073    bases: &'bases BaseAddresses,
1074    section: &Section,
1075    input: &mut R,
1076) -> Result<Option<CieOrFde<'bases, Section, R>>>
1077where
1078    R: Reader,
1079    Section: UnwindSection<R>,
1080{
1081    let offset = input.offset_from(section.section());
1082    let (length, format) = input.read_initial_length()?;
1083    if length.into_u64() == 0 {
1084        return Ok(None);
1085    }
1086
1087    let mut rest = input.split(length)?;
1088    let cie_offset_base = rest.offset_from(section.section());
1089    let cie_id_or_offset = match Section::cie_offset_encoding(format) {
1090        CieOffsetEncoding::U32 => rest.read_u32().map(u64::from)?,
1091        CieOffsetEncoding::U64 => rest.read_u64()?,
1092    };
1093
1094    if Section::is_cie(format, cie_id_or_offset) {
1095        let cie = CommonInformationEntry::parse_rest(offset, length, format, bases, section, rest)?;
1096        Ok(Some(CieOrFde::Cie(cie)))
1097    } else {
1098        let cie_offset = R::Offset::from_u64(cie_id_or_offset)?;
1099        let cie_offset = match section.resolve_cie_offset(cie_offset_base, cie_offset) {
1100            None => return Err(Error::OffsetOutOfBounds),
1101            Some(cie_offset) => cie_offset,
1102        };
1103
1104        let fde = PartialFrameDescriptionEntry {
1105            offset,
1106            length,
1107            format,
1108            cie_offset: cie_offset.into(),
1109            rest,
1110            section: section.clone(),
1111            bases,
1112        };
1113
1114        Ok(Some(CieOrFde::Fde(fde)))
1115    }
1116}
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)]
1122pub 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
1154impl Augmentation {
1155    fn parse<Section, R>(
1156        augmentation_str: &mut R,
1157        bases: &BaseAddresses,
1158        address_size: u8,
1159        section: &Section,
1160        input: &mut R,
1161    ) -> Result<Augmentation>
1162    where
1163        R: Reader,
1164        Section: UnwindSection<R>,
1165    {
1166        debug_assert!(
1167            !augmentation_str.is_empty(),
1168            "Augmentation::parse should only be called if we have an augmentation"
1169        );
1170
1171        let mut augmentation = Augmentation::default();
1172
1173        let mut parsed_first = false;
1174        let mut data = None;
1175
1176        while !augmentation_str.is_empty() {
1177            let ch = augmentation_str.read_u8()?;
1178            match ch {
1179                b'z' => {
1180                    if parsed_first {
1181                        return Err(Error::UnknownAugmentation);
1182                    }
1183
1184                    let augmentation_length = input.read_uleb128().and_then(R::Offset::from_u64)?;
1185                    data = Some(input.split(augmentation_length)?);
1186                }
1187                b'L' => {
1188                    let rest = data.as_mut().ok_or(Error::UnknownAugmentation)?;
1189                    let encoding = parse_pointer_encoding(rest)?;
1190                    augmentation.lsda = Some(encoding);
1191                }
1192                b'P' => {
1193                    let rest = data.as_mut().ok_or(Error::UnknownAugmentation)?;
1194                    let encoding = parse_pointer_encoding(rest)?;
1195                    let parameters = PointerEncodingParameters {
1196                        bases: &bases.eh_frame,
1197                        func_base: None,
1198                        address_size,
1199                        section: section.section(),
1200                    };
1201
1202                    let personality = parse_encoded_pointer(encoding, &parameters, rest)?;
1203                    augmentation.personality = Some((encoding, personality));
1204                }
1205                b'R' => {
1206                    let rest = data.as_mut().ok_or(Error::UnknownAugmentation)?;
1207                    let encoding = parse_pointer_encoding(rest)?;
1208                    augmentation.fde_address_encoding = Some(encoding);
1209                }
1210                b'S' => augmentation.is_signal_trampoline = true,
1211                _ => return Err(Error::UnknownAugmentation),
1212            }
1213
1214            parsed_first = true;
1215        }
1216
1217        Ok(augmentation)
1218    }
1219}
1220
1221/// Parsed augmentation data for a `FrameDescriptEntry`.
1222#[derive(Clone, Debug, Default, PartialEq, Eq)]
1223struct AugmentationData {
1224    lsda: Option<Pointer>,
1225}
1226
1227impl AugmentationData {
1228    fn parse<R: Reader>(
1229        augmentation: &Augmentation,
1230        encoding_parameters: &PointerEncodingParameters<'_, R>,
1231        input: &mut R,
1232    ) -> 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        let aug_data_len = input.read_uleb128().and_then(R::Offset::from_u64)?;
1240        let rest = &mut input.split(aug_data_len)?;
1241        let mut augmentation_data = AugmentationData::default();
1242        if let Some(encoding) = augmentation.lsda {
1243            let lsda = parse_encoded_pointer(encoding, encoding_parameters, rest)?;
1244            augmentation_data.lsda = Some(lsda);
1245        }
1246        Ok(augmentation_data)
1247    }
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)]
1254pub struct CommonInformationEntry<R, Offset = <R as Reader>::Offset>
1255where
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
1308impl<R: Reader> CommonInformationEntry<R> {
1309    fn parse<Section: UnwindSection<R>>(
1310        bases: &BaseAddresses,
1311        section: &Section,
1312        input: &mut R,
1313    ) -> Result<CommonInformationEntry<R>> {
1314        match parse_cfi_entry(bases, section, input)? {
1315            Some(CieOrFde::Cie(cie)) => Ok(cie),
1316            Some(CieOrFde::Fde(_)) => Err(Error::NotCieId),
1317            None => Err(Error::NoEntryAtGivenOffset),
1318        }
1319    }
1320
1321    fn parse_rest<Section: UnwindSection<R>>(
1322        offset: R::Offset,
1323        length: R::Offset,
1324        format: Format,
1325        bases: &BaseAddresses,
1326        section: &Section,
1327        mut rest: R,
1328    ) -> Result<CommonInformationEntry<R>> {
1329        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        match version {
1335            1 | 3 | 4 => (),
1336            _ => return Err(Error::UnknownVersion(u64::from(version))),
1337        }
1338
1339        let mut augmentation_string = rest.read_null_terminated_slice()?;
1340
1341        let address_size = if Section::has_address_and_segment_sizes(version) {
1342            let address_size = rest.read_address_size()?;
1343            let segment_size = rest.read_u8()?;
1344            if segment_size != 0 {
1345                return Err(Error::UnsupportedSegmentSize);
1346            }
1347            address_size
1348        } else {
1349            section.address_size()
1350        };
1351
1352        let code_alignment_factor = rest.read_uleb128()?;
1353        let data_alignment_factor = rest.read_sleb128()?;
1354
1355        let return_address_register = if version == 1 {
1356            Register(rest.read_u8()?.into())
1357        } else {
1358            rest.read_uleb128().and_then(Register::from_u64)?
1359        };
1360
1361        let augmentation = if augmentation_string.is_empty() {
1362            None
1363        } else {
1364            Some(Augmentation::parse(
1365                &mut augmentation_string,
1366                bases,
1367                address_size,
1368                section,
1369                &mut rest,
1370            )?)
1371        };
1372
1373        let entry = CommonInformationEntry {
1374            offset,
1375            length,
1376            format,
1377            version,
1378            augmentation,
1379            address_size,
1380            code_alignment_factor,
1381            data_alignment_factor,
1382            return_address_register,
1383            initial_instructions: rest,
1384        };
1385
1386        Ok(entry)
1387    }
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.
1394impl<R: Reader> CommonInformationEntry<R> {
1395    /// Get the offset of this entry from the start of its containing section.
1396    pub fn offset(&self) -> R::Offset {
1397        self.offset
1398    }
1399
1400    /// Return the encoding parameters for this CIE.
1401    pub fn encoding(&self) -> Encoding {
1402        Encoding {
1403            format: self.format,
1404            version: u16::from(self.version),
1405            address_size: self.address_size,
1406        }
1407    }
1408
1409    /// The size of addresses (in bytes) in this CIE.
1410    pub fn address_size(&self) -> u8 {
1411        self.address_size
1412    }
1413
1414    /// Iterate over this CIE's initial instructions.
1415    ///
1416    /// Can be [used with
1417    /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
1418    pub fn instructions<'a, Section>(
1419        &self,
1420        section: &'a Section,
1421        bases: &'a BaseAddresses,
1422    ) -> CallFrameInstructionIter<'a, R>
1423    where
1424        Section: UnwindSection<R>,
1425    {
1426        CallFrameInstructionIter {
1427            input: self.initial_instructions.clone(),
1428            address_encoding: None,
1429            parameters: PointerEncodingParameters {
1430                bases: &bases.eh_frame,
1431                func_base: None,
1432                address_size: self.address_size,
1433                section: section.section(),
1434            },
1435            vendor: section.vendor(),
1436        }
1437    }
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    pub fn entry_len(&self) -> R::Offset {
1444        self.length
1445    }
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    pub fn version(&self) -> u8 {
1450        self.version
1451    }
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    pub fn augmentation(&self) -> Option<&Augmentation> {
1458        self.augmentation.as_ref()
1459    }
1460
1461    /// True if this CIE's FDEs have a LSDA.
1462    pub fn has_lsda(&self) -> bool {
1463        self.augmentation.map_or(false, |a| a.lsda.is_some())
1464    }
1465
1466    /// Return the encoding of the LSDA address for this CIE's FDEs.
1467    pub fn lsda_encoding(&self) -> Option<constants::DwEhPe> {
1468        self.augmentation.and_then(|a| a.lsda)
1469    }
1470
1471    /// Return the encoding and address of the personality routine handler
1472    /// for this CIE's FDEs.
1473    pub fn personality_with_encoding(&self) -> Option<(constants::DwEhPe, Pointer)> {
1474        self.augmentation.as_ref().and_then(|a| a.personality)
1475    }
1476
1477    /// Return the address of the personality routine handler
1478    /// for this CIE's FDEs.
1479    pub fn personality(&self) -> Option<Pointer> {
1480        self.augmentation
1481            .as_ref()
1482            .and_then(|a| a.personality)
1483            .map(|(_, p)| p)
1484    }
1485
1486    /// Return the encoding of the addresses for this CIE's FDEs.
1487    pub fn fde_address_encoding(&self) -> Option<constants::DwEhPe> {
1488        self.augmentation.and_then(|a| a.fde_address_encoding)
1489    }
1490
1491    /// True if this CIE's FDEs are trampolines for signal handlers.
1492    pub fn is_signal_trampoline(&self) -> bool {
1493        self.augmentation.map_or(false, |a| a.is_signal_trampoline)
1494    }
1495
1496    /// > A constant that is factored out of all advance location instructions
1497    /// > (see Section 6.4.2.1).
1498    pub fn code_alignment_factor(&self) -> u64 {
1499        self.code_alignment_factor
1500    }
1501
1502    /// > A constant that is factored out of certain offset instructions (see
1503    /// > below). The resulting value is (operand * data_alignment_factor).
1504    pub fn data_alignment_factor(&self) -> i64 {
1505        self.data_alignment_factor
1506    }
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    pub fn return_address_register(&self) -> Register {
1512        self.return_address_register
1513    }
1514}
1515
1516/// A partially parsed `FrameDescriptionEntry`.
1517///
1518/// Fully parsing this FDE requires first parsing its CIE.
1519#[derive(Clone, Debug, PartialEq, Eq)]
1520pub struct PartialFrameDescriptionEntry<'bases, Section, R>
1521where
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
1534impl<'bases, Section, R> PartialFrameDescriptionEntry<'bases, Section, R>
1535where
1536    R: Reader,
1537    Section: UnwindSection<R>,
1538{
1539    fn parse_partial(
1540        section: &Section,
1541        bases: &'bases BaseAddresses,
1542        input: &mut R,
1543    ) -> Result<PartialFrameDescriptionEntry<'bases, Section, R>> {
1544        match parse_cfi_entry(bases, section, input)? {
1545            Some(CieOrFde::Cie(_)) => Err(Error::NotFdePointer),
1546            Some(CieOrFde::Fde(partial)) => Ok(partial),
1547            None => Err(Error::NoEntryAtGivenOffset),
1548        }
1549    }
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    pub fn parse<F>(&self, get_cie: F) -> Result<FrameDescriptionEntry<R>>
1557    where
1558        F: FnMut(&Section, &BaseAddresses, Section::Offset) -> Result<CommonInformationEntry<R>>,
1559    {
1560        FrameDescriptionEntry::parse_rest(
1561            self.offset,
1562            self.length,
1563            self.format,
1564            self.cie_offset,
1565            self.rest.clone(),
1566            &self.section,
1567            self.bases,
1568            get_cie,
1569        )
1570    }
1571
1572    /// Get the offset of this entry from the start of its containing section.
1573    pub fn offset(&self) -> R::Offset {
1574        self.offset
1575    }
1576
1577    /// Get the offset of this FDE's CIE.
1578    pub fn cie_offset(&self) -> Section::Offset {
1579        self.cie_offset
1580    }
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    pub fn entry_len(&self) -> R::Offset {
1587        self.length
1588    }
1589}
1590
1591/// A `FrameDescriptionEntry` is a set of CFA instructions for an address range.
1592#[derive(Clone, Debug, PartialEq, Eq)]
1593pub struct FrameDescriptionEntry<R, Offset = <R as Reader>::Offset>
1594where
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
1633impl<R: Reader> FrameDescriptionEntry<R> {
1634    fn parse_rest<Section, F>(
1635        offset: R::Offset,
1636        length: R::Offset,
1637        format: Format,
1638        cie_pointer: Section::Offset,
1639        mut rest: R,
1640        section: &Section,
1641        bases: &BaseAddresses,
1642        mut get_cie: F,
1643    ) -> Result<FrameDescriptionEntry<R>>
1644    where
1645        Section: UnwindSection<R>,
1646        F: FnMut(&Section, &BaseAddresses, Section::Offset) -> Result<CommonInformationEntry<R>>,
1647    {
1648        let cie = get_cie(section, bases, cie_pointer)?;
1649
1650        let mut parameters = PointerEncodingParameters {
1651            bases: &bases.eh_frame,
1652            func_base: None,
1653            address_size: cie.address_size,
1654            section: section.section(),
1655        };
1656
1657        let (initial_address, address_range) = Self::parse_addresses(&mut rest, &cie, &parameters)?;
1658        parameters.func_base = Some(initial_address);
1659
1660        let aug_data = if let Some(ref augmentation) = cie.augmentation {
1661            Some(AugmentationData::parse(
1662                augmentation,
1663                &parameters,
1664                &mut rest,
1665            )?)
1666        } else {
1667            None
1668        };
1669
1670        let entry = FrameDescriptionEntry {
1671            offset,
1672            length,
1673            format,
1674            cie,
1675            initial_address,
1676            address_range,
1677            augmentation: aug_data,
1678            instructions: rest,
1679        };
1680
1681        Ok(entry)
1682    }
1683
1684    fn parse_addresses(
1685        input: &mut R,
1686        cie: &CommonInformationEntry<R>,
1687        parameters: &PointerEncodingParameters<'_, R>,
1688    ) -> Result<(u64, u64)> {
1689        let encoding = cie.augmentation().and_then(|a| a.fde_address_encoding);
1690        if let Some(encoding) = encoding {
1691            // Ignore indirection.
1692            let initial_address = parse_encoded_pointer(encoding, parameters, input)?.pointer();
1693            let address_range = parse_encoded_value(encoding, parameters, input)?;
1694            Ok((initial_address, address_range))
1695        } else {
1696            let initial_address = input.read_address(cie.address_size)?;
1697            let address_range = input.read_address(cie.address_size)?;
1698            Ok((initial_address, address_range))
1699        }
1700    }
1701
1702    /// Return the table of unwind information for this FDE.
1703    #[inline]
1704    pub fn rows<'a, 'ctx, Section, S>(
1705        &self,
1706        section: &'a Section,
1707        bases: &'a BaseAddresses,
1708        ctx: &'ctx mut UnwindContext<R::Offset, S>,
1709    ) -> Result<UnwindTable<'a, 'ctx, R, S>>
1710    where
1711        Section: UnwindSection<R>,
1712        S: UnwindContextStorage<R::Offset>,
1713    {
1714        UnwindTable::new(section, bases, ctx, self)
1715    }
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    pub fn unwind_info_for_address<'ctx, Section, S>(
1724        &self,
1725        section: &Section,
1726        bases: &BaseAddresses,
1727        ctx: &'ctx mut UnwindContext<R::Offset, S>,
1728        address: u64,
1729    ) -> Result<&'ctx UnwindTableRow<R::Offset, S>>
1730    where
1731        Section: UnwindSection<R>,
1732        S: UnwindContextStorage<R::Offset>,
1733    {
1734        let mut table = self.rows(section, bases, ctx)?;
1735        while let Some(row) = table.next_row()? {
1736            if row.contains(address) {
1737                return Ok(table.ctx.row());
1738            }
1739        }
1740        Err(Error::NoUnwindInfoForAddress)
1741    }
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)]
1749impl<R: Reader> FrameDescriptionEntry<R> {
1750    /// Get the offset of this entry from the start of its containing section.
1751    pub fn offset(&self) -> R::Offset {
1752        self.offset
1753    }
1754
1755    /// Get a reference to this FDE's CIE.
1756    pub fn cie(&self) -> &CommonInformationEntry<R> {
1757        &self.cie
1758    }
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    pub fn entry_len(&self) -> R::Offset {
1765        self.length
1766    }
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    pub fn instructions<'a, Section>(
1776        &self,
1777        section: &'a Section,
1778        bases: &'a BaseAddresses,
1779    ) -> CallFrameInstructionIter<'a, R>
1780    where
1781        Section: UnwindSection<R>,
1782    {
1783        CallFrameInstructionIter {
1784            input: self.instructions.clone(),
1785            address_encoding: self.cie.augmentation().and_then(|a| a.fde_address_encoding),
1786            parameters: PointerEncodingParameters {
1787                bases: &bases.eh_frame,
1788                func_base: None,
1789                address_size: self.cie.address_size,
1790                section: section.section(),
1791            },
1792            vendor: section.vendor(),
1793        }
1794    }
1795
1796    /// The first address for which this entry has unwind information for.
1797    pub fn initial_address(&self) -> u64 {
1798        self.initial_address
1799    }
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    pub fn end_address(&self) -> u64 {
1806        self.initial_address
1807            .wrapping_add_sized(self.address_range, self.cie.address_size)
1808    }
1809
1810    /// The number of bytes of instructions that this entry has unwind
1811    /// information for.
1812    pub fn len(&self) -> u64 {
1813        self.address_range
1814    }
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    pub fn contains(&self, address: u64) -> bool {
1822        self.initial_address() <= address && address < self.end_address()
1823    }
1824
1825    /// The address of this FDE's language-specific data area (LSDA), if it has
1826    /// any.
1827    pub fn lsda(&self) -> Option<Pointer> {
1828        self.augmentation.as_ref().and_then(|a| a.lsda)
1829    }
1830
1831    /// Return true if this FDE's function is a trampoline for a signal handler.
1832    #[inline]
1833    pub fn is_signal_trampoline(&self) -> bool {
1834        self.cie().is_signal_trampoline()
1835    }
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    pub fn personality(&self) -> Option<Pointer> {
1842        self.cie().personality()
1843    }
1844}
1845
1846/// Specification of what storage should be used for [`UnwindContext`].
1847///
1848#[cfg_attr(
1849    feature = "read",
1850    doc = "
1851Normally you would only need to use [`StoreOnHeap`], which places the stack
1852on the heap using [`Box`]. This is the default storage type parameter for [`UnwindContext`].
1853
1854You 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/// ```
1896pub 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")]
1907const MAX_RULES: usize = 192;
1908#[cfg(feature = "read")]
1909const MAX_UNWIND_STACK_DEPTH: usize = 4;
1910
1911#[cfg(feature = "read")]
1912impl<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)]
1951pub struct UnwindContext<T, S = StoreOnHeap>
1952where
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
1974impl<T, S> Debug for UnwindContext<T, S>
1975where
1976    T: ReaderOffset,
1977    S: UnwindContextStorage<T>,
1978{
1979    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1980        f.debug_struct("UnwindContext")
1981            .field("stack", &self.stack)
1982            .field("initial_rule", &self.initial_rule)
1983            .field("is_initialized", &self.is_initialized)
1984            .finish()
1985    }
1986}
1987
1988impl<T, S> Default for UnwindContext<T, S>
1989where
1990    T: ReaderOffset,
1991    S: UnwindContextStorage<T>,
1992{
1993    fn default() -> Self {
1994        Self::new_in()
1995    }
1996}
1997
1998#[cfg(feature = "read")]
1999impl<T: ReaderOffset> UnwindContext<T> {
2000    /// Construct a new call frame unwinding context.
2001    pub fn new() -> Self {
2002        Self::new_in()
2003    }
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.
2010impl<T, S> UnwindContext<T, S>
2011where
2012    T: ReaderOffset,
2013    S: UnwindContextStorage<T>,
2014{
2015    /// Construct a new call frame unwinding context.
2016    pub fn new_in() -> Self {
2017        let mut ctx = UnwindContext {
2018            stack: Default::default(),
2019            initial_rule: None,
2020            is_initialized: false,
2021        };
2022        ctx.reset();
2023        ctx
2024    }
2025
2026    /// Run the CIE's initial instructions and initialize this `UnwindContext`.
2027    fn initialize<Section, R>(
2028        &mut self,
2029        section: &Section,
2030        bases: &BaseAddresses,
2031        cie: &CommonInformationEntry<R>,
2032    ) -> Result<()>
2033    where
2034        R: Reader<Offset = T>,
2035        Section: UnwindSection<R>,
2036    {
2037        // Always reset because previous initialization failure may leave dirty state.
2038        self.reset();
2039
2040        let mut table = UnwindTable::new_for_cie(section, bases, self, cie);
2041        while table.next_row()?.is_some() {}
2042
2043        self.save_initial_rules()?;
2044        Ok(())
2045    }
2046
2047    fn reset(&mut self) {
2048        self.stack.clear();
2049        self.stack.try_push(UnwindTableRow::default()).unwrap();
2050        debug_assert!(self.stack[0].is_default());
2051        self.initial_rule = None;
2052        self.is_initialized = false;
2053    }
2054
2055    fn row(&self) -> &UnwindTableRow<T, S> {
2056        self.stack.last().unwrap()
2057    }
2058
2059    fn row_mut(&mut self) -> &mut UnwindTableRow<T, S> {
2060        self.stack.last_mut().unwrap()
2061    }
2062
2063    fn save_initial_rules(&mut self) -> Result<()> {
2064        debug_assert!(!self.is_initialized);
2065        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            [] => Some((Register(0), RegisterRule::Undefined)),
2069            [ref rule] => Some(rule.clone()),
2070            _ => {
2071                let rules = self.stack.last().unwrap().clone();
2072                self.stack
2073                    .try_insert(0, rules)
2074                    .map_err(|_| Error::StackFull)?;
2075                None
2076            }
2077        };
2078        self.is_initialized = true;
2079        Ok(())
2080    }
2081
2082    fn start_address(&self) -> u64 {
2083        self.row().start_address
2084    }
2085
2086    fn set_start_address(&mut self, start_address: u64) {
2087        let row = self.row_mut();
2088        row.start_address = start_address;
2089    }
2090
2091    fn set_register_rule(&mut self, register: Register, rule: RegisterRule<T>) -> Result<()> {
2092        let row = self.row_mut();
2093        row.registers.set(register, rule)
2094    }
2095
2096    /// Returns `None` if we have not completed evaluation of a CIE's initial
2097    /// instructions.
2098    fn get_initial_rule(&self, register: Register) -> Option<RegisterRule<T>> {
2099        if !self.is_initialized {
2100            return None;
2101        }
2102        Some(match self.initial_rule {
2103            None => self.stack[0].registers.get(register),
2104            Some((r, ref rule)) if r == register => rule.clone(),
2105            _ => RegisterRule::Undefined,
2106        })
2107    }
2108
2109    fn set_cfa(&mut self, cfa: CfaRule<T>) {
2110        self.row_mut().cfa = cfa;
2111    }
2112
2113    fn cfa_mut(&mut self) -> &mut CfaRule<T> {
2114        &mut self.row_mut().cfa
2115    }
2116
2117    fn push_row(&mut self) -> Result<()> {
2118        let new_row = self.row().clone();
2119        self.stack.try_push(new_row).map_err(|_| Error::StackFull)
2120    }
2121
2122    fn pop_row(&mut self) -> Result<()> {
2123        let min_size = if self.is_initialized && self.initial_rule.is_none() {
2124            2
2125        } else {
2126            1
2127        };
2128        if self.stack.len() <= min_size {
2129            return Err(Error::PopWithEmptyStack);
2130        }
2131        self.stack.pop().unwrap();
2132        Ok(())
2133    }
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)]
2193pub struct UnwindTable<'a, 'ctx, R, S = StoreOnHeap>
2194where
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.
2213impl<'a, 'ctx, R, S> UnwindTable<'a, 'ctx, R, S>
2214where
2215    R: Reader,
2216    S: UnwindContextStorage<R::Offset>,
2217{
2218    /// Construct a new `UnwindTable` for the given
2219    /// `FrameDescriptionEntry`'s CFI unwinding program.
2220    pub fn new<Section: UnwindSection<R>>(
2221        section: &'a Section,
2222        bases: &'a BaseAddresses,
2223        ctx: &'ctx mut UnwindContext<R::Offset, S>,
2224        fde: &FrameDescriptionEntry<R>,
2225    ) -> Result<Self> {
2226        ctx.initialize(section, bases, fde.cie())?;
2227        Ok(Self::new_for_fde(section, bases, ctx, fde))
2228    }
2229
2230    fn new_for_fde<Section: UnwindSection<R>>(
2231        section: &'a Section,
2232        bases: &'a BaseAddresses,
2233        ctx: &'ctx mut UnwindContext<R::Offset, S>,
2234        fde: &FrameDescriptionEntry<R>,
2235    ) -> Self {
2236        assert!(!ctx.stack.is_empty());
2237        UnwindTable {
2238            code_alignment_factor: Wrapping(fde.cie().code_alignment_factor()),
2239            data_alignment_factor: Wrapping(fde.cie().data_alignment_factor()),
2240            address_size: fde.cie().address_size,
2241            next_start_address: fde.initial_address(),
2242            last_end_address: fde.end_address(),
2243            returned_last_row: false,
2244            current_row_valid: false,
2245            instructions: fde.instructions(section, bases),
2246            ctx,
2247        }
2248    }
2249
2250    fn new_for_cie<Section: UnwindSection<R>>(
2251        section: &'a Section,
2252        bases: &'a BaseAddresses,
2253        ctx: &'ctx mut UnwindContext<R::Offset, S>,
2254        cie: &CommonInformationEntry<R>,
2255    ) -> Self {
2256        assert!(!ctx.stack.is_empty());
2257        UnwindTable {
2258            code_alignment_factor: Wrapping(cie.code_alignment_factor()),
2259            data_alignment_factor: Wrapping(cie.data_alignment_factor()),
2260            address_size: cie.address_size,
2261            next_start_address: 0,
2262            last_end_address: 0,
2263            returned_last_row: false,
2264            current_row_valid: false,
2265            instructions: cie.instructions(section, bases),
2266            ctx,
2267        }
2268    }
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    pub fn next_row(&mut self) -> Result<Option<&UnwindTableRow<R::Offset, S>>> {
2276        assert!(!self.ctx.stack.is_empty());
2277        self.ctx.set_start_address(self.next_start_address);
2278        self.current_row_valid = false;
2279
2280        loop {
2281            match self.instructions.next() {
2282                Err(e) => return Err(e),
2283
2284                Ok(None) => {
2285                    if self.returned_last_row {
2286                        return Ok(None);
2287                    }
2288
2289                    let row = self.ctx.row_mut();
2290                    row.end_address = self.last_end_address;
2291
2292                    self.returned_last_row = true;
2293                    self.current_row_valid = true;
2294                    return Ok(Some(row));
2295                }
2296
2297                Ok(Some(instruction)) => {
2298                    if self.evaluate(instruction)? {
2299                        self.current_row_valid = true;
2300                        return Ok(Some(self.ctx.row()));
2301                    }
2302                }
2303            };
2304        }
2305    }
2306
2307    /// Returns the current row with the lifetime of the context.
2308    pub fn into_current_row(self) -> Option<&'ctx UnwindTableRow<R::Offset, S>> {
2309        if self.current_row_valid {
2310            Some(self.ctx.row())
2311        } else {
2312            None
2313        }
2314    }
2315
2316    /// Evaluate one call frame instruction. Return `Ok(true)` if the row is
2317    /// complete, `Ok(false)` otherwise.
2318    fn evaluate(&mut self, instruction: CallFrameInstruction<R::Offset>) -> Result<bool> {
2319        use crate::CallFrameInstruction::*;
2320
2321        match instruction {
2322            // Instructions that complete the current row and advance the
2323            // address for the next row.
2324            SetLoc { address } => {
2325                if address < self.ctx.start_address() {
2326                    return Err(Error::InvalidAddressRange);
2327                }
2328
2329                self.next_start_address = address;
2330                self.ctx.row_mut().end_address = self.next_start_address;
2331                return Ok(true);
2332            }
2333            AdvanceLoc { delta } => {
2334                let delta = Wrapping(u64::from(delta)) * self.code_alignment_factor;
2335                self.next_start_address = self
2336                    .ctx
2337                    .start_address()
2338                    .add_sized(delta.0, self.address_size)?;
2339                self.ctx.row_mut().end_address = self.next_start_address;
2340                return Ok(true);
2341            }
2342
2343            // Instructions that modify the CFA.
2344            DefCfa { register, offset } => {
2345                self.ctx.set_cfa(CfaRule::RegisterAndOffset {
2346                    register,
2347                    offset: offset as i64,
2348                });
2349            }
2350            DefCfaSf {
2351                register,
2352                factored_offset,
2353            } => {
2354                let data_align = self.data_alignment_factor;
2355                self.ctx.set_cfa(CfaRule::RegisterAndOffset {
2356                    register,
2357                    offset: (Wrapping(factored_offset) * data_align).0,
2358                });
2359            }
2360            DefCfaRegister { register } => {
2361                if let CfaRule::RegisterAndOffset {
2362                    register: ref mut reg,
2363                    ..
2364                } = *self.ctx.cfa_mut()
2365                {
2366                    *reg = register;
2367                } else {
2368                    return Err(Error::CfiInstructionInInvalidContext);
2369                }
2370            }
2371            DefCfaOffset { offset } => {
2372                if let CfaRule::RegisterAndOffset {
2373                    offset: ref mut off,
2374                    ..
2375                } = *self.ctx.cfa_mut()
2376                {
2377                    *off = offset as i64;
2378                } else {
2379                    return Err(Error::CfiInstructionInInvalidContext);
2380                }
2381            }
2382            DefCfaOffsetSf { factored_offset } => {
2383                if let CfaRule::RegisterAndOffset {
2384                    offset: ref mut off,
2385                    ..
2386                } = *self.ctx.cfa_mut()
2387                {
2388                    let data_align = self.data_alignment_factor;
2389                    *off = (Wrapping(factored_offset) * data_align).0;
2390                } else {
2391                    return Err(Error::CfiInstructionInInvalidContext);
2392                }
2393            }
2394            DefCfaExpression { expression } => {
2395                self.ctx.set_cfa(CfaRule::Expression(expression));
2396            }
2397
2398            // Instructions that define register rules.
2399            Undefined { register } => {
2400                self.ctx
2401                    .set_register_rule(register, RegisterRule::Undefined)?;
2402            }
2403            SameValue { register } => {
2404                self.ctx
2405                    .set_register_rule(register, RegisterRule::SameValue)?;
2406            }
2407            Offset {
2408                register,
2409                factored_offset,
2410            } => {
2411                let offset = Wrapping(factored_offset as i64) * self.data_alignment_factor;
2412                self.ctx
2413                    .set_register_rule(register, RegisterRule::Offset(offset.0))?;
2414            }
2415            OffsetExtendedSf {
2416                register,
2417                factored_offset,
2418            } => {
2419                let offset = Wrapping(factored_offset) * self.data_alignment_factor;
2420                self.ctx
2421                    .set_register_rule(register, RegisterRule::Offset(offset.0))?;
2422            }
2423            ValOffset {
2424                register,
2425                factored_offset,
2426            } => {
2427                let offset = Wrapping(factored_offset as i64) * self.data_alignment_factor;
2428                self.ctx
2429                    .set_register_rule(register, RegisterRule::ValOffset(offset.0))?;
2430            }
2431            ValOffsetSf {
2432                register,
2433                factored_offset,
2434            } => {
2435                let offset = Wrapping(factored_offset) * self.data_alignment_factor;
2436                self.ctx
2437                    .set_register_rule(register, RegisterRule::ValOffset(offset.0))?;
2438            }
2439            Register {
2440                dest_register,
2441                src_register,
2442            } => {
2443                self.ctx
2444                    .set_register_rule(dest_register, RegisterRule::Register(src_register))?;
2445            }
2446            Expression {
2447                register,
2448                expression,
2449            } => {
2450                let expression = RegisterRule::Expression(expression);
2451                self.ctx.set_register_rule(register, expression)?;
2452            }
2453            ValExpression {
2454                register,
2455                expression,
2456            } => {
2457                let expression = RegisterRule::ValExpression(expression);
2458                self.ctx.set_register_rule(register, expression)?;
2459            }
2460            Restore { register } => {
2461                let initial_rule = if let Some(rule) = self.ctx.get_initial_rule(register) {
2462                    rule
2463                } else {
2464                    // Can't restore the initial rule when we are
2465                    // evaluating the initial rules!
2466                    return Err(Error::CfiInstructionInInvalidContext);
2467                };
2468
2469                self.ctx.set_register_rule(register, initial_rule)?;
2470            }
2471
2472            // Row push and pop instructions.
2473            RememberState => {
2474                self.ctx.push_row()?;
2475            }
2476            RestoreState => {
2477                // Pop state while preserving current location.
2478                let start_address = self.ctx.start_address();
2479                self.ctx.pop_row()?;
2480                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            ArgsSize { size } => {
2486                self.ctx.row_mut().saved_args_size = size;
2487            }
2488
2489            // AArch64 extension.
2490            NegateRaState => {
2491                let register = crate::AArch64::RA_SIGN_STATE;
2492                let value = match self.ctx.row().register(register) {
2493                    RegisterRule::Undefined => 0,
2494                    RegisterRule::Constant(value) => value,
2495                    _ => return Err(Error::CfiInstructionInInvalidContext),
2496                };
2497                self.ctx
2498                    .set_register_rule(register, RegisterRule::Constant(value ^ 1))?;
2499            }
2500
2501            // No operation.
2502            Nop => {}
2503        };
2504
2505        Ok(false)
2506    }
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
2530struct RegisterRuleMap<T, S = StoreOnHeap>
2531where
2532    T: ReaderOffset,
2533    S: UnwindContextStorage<T>,
2534{
2535    rules: ArrayVec<S::Rules>,
2536}
2537
2538impl<T, S> Debug for RegisterRuleMap<T, S>
2539where
2540    T: ReaderOffset,
2541    S: UnwindContextStorage<T>,
2542{
2543    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2544        f.debug_struct("RegisterRuleMap")
2545            .field("rules", &self.rules)
2546            .finish()
2547    }
2548}
2549
2550impl<T, S> Clone for RegisterRuleMap<T, S>
2551where
2552    T: ReaderOffset,
2553    S: UnwindContextStorage<T>,
2554{
2555    fn clone(&self) -> Self {
2556        Self {
2557            rules: self.rules.clone(),
2558        }
2559    }
2560}
2561
2562impl<T, S> Default for RegisterRuleMap<T, S>
2563where
2564    T: ReaderOffset,
2565    S: UnwindContextStorage<T>,
2566{
2567    fn default() -> Self {
2568        RegisterRuleMap {
2569            rules: Default::default(),
2570        }
2571    }
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.
2578impl<T, S> RegisterRuleMap<T, S>
2579where
2580    T: ReaderOffset,
2581    S: UnwindContextStorage<T>,
2582{
2583    fn is_default(&self) -> bool {
2584        self.rules.is_empty()
2585    }
2586
2587    fn get(&self, register: Register) -> RegisterRule<T> {
2588        self.rules
2589            .iter()
2590            .find(|rule| rule.0 == register)
2591            .map(|r| {
2592                debug_assert!(r.1.is_defined());
2593                r.1.clone()
2594            })
2595            .unwrap_or(RegisterRule::Undefined)
2596    }
2597
2598    fn set(&mut self, register: Register, rule: RegisterRule<T>) -> Result<()> {
2599        if !rule.is_defined() {
2600            let idx = self
2601                .rules
2602                .iter()
2603                .enumerate()
2604                .find(|&(_, r)| r.0 == register)
2605                .map(|(i, _)| i);
2606            if let Some(idx) = idx {
2607                self.rules.swap_remove(idx);
2608            }
2609            return Ok(());
2610        }
2611
2612        for &mut (reg, ref mut old_rule) in &mut *self.rules {
2613            debug_assert!(old_rule.is_defined());
2614            if reg == register {
2615                *old_rule = rule;
2616                return Ok(());
2617            }
2618        }
2619
2620        self.rules
2621            .try_push((register, rule))
2622            .map_err(|_| Error::TooManyRegisterRules)
2623    }
2624
2625    fn iter(&self) -> RegisterRuleIter<'_, T> {
2626        RegisterRuleIter(self.rules.iter())
2627    }
2628}
2629
2630impl<'a, R, S> FromIterator<&'a (Register, RegisterRule<R>)> for RegisterRuleMap<R, S>
2631where
2632    R: 'a + ReaderOffset,
2633    S: UnwindContextStorage<R>,
2634{
2635    fn from_iter<T>(iter: T) -> Self
2636    where
2637        T: IntoIterator<Item = &'a (Register, RegisterRule<R>)>,
2638    {
2639        let iter = iter.into_iter();
2640        let mut rules = RegisterRuleMap::default();
2641        for &(reg, ref rule) in iter.filter(|r| r.1.is_defined()) {
2642            rules.set(reg, rule.clone()).expect(
2643                "This is only used in tests, impl isn't exposed publicly.
2644                         If you trip this, fix your test",
2645            );
2646        }
2647        rules
2648    }
2649}
2650
2651impl<T, S> PartialEq for RegisterRuleMap<T, S>
2652where
2653    T: ReaderOffset + PartialEq,
2654    S: UnwindContextStorage<T>,
2655{
2656    fn eq(&self, rhs: &Self) -> bool {
2657        for &(reg, ref rule) in &*self.rules {
2658            debug_assert!(rule.is_defined());
2659            if *rule != rhs.get(reg) {
2660                return false;
2661            }
2662        }
2663
2664        for &(reg, ref rhs_rule) in &*rhs.rules {
2665            debug_assert!(rhs_rule.is_defined());
2666            if *rhs_rule != self.get(reg) {
2667                return false;
2668            }
2669        }
2670
2671        true
2672    }
2673}
2674
2675impl<T, S> Eq for RegisterRuleMap<T, S>
2676where
2677    T: ReaderOffset + Eq,
2678    S: UnwindContextStorage<T>,
2679{
2680}
2681
2682/// An unordered iterator for register rules.
2683#[derive(Debug, Clone)]
2684pub struct RegisterRuleIter<'iter, T>(::core::slice::Iter<'iter, (Register, RegisterRule<T>)>)
2685where
2686    T: ReaderOffset;
2687
2688impl<'iter, T: ReaderOffset> Iterator for RegisterRuleIter<'iter, T> {
2689    type Item = &'iter (Register, RegisterRule<T>);
2690
2691    fn next(&mut self) -> Option<Self::Item> {
2692        self.0.next()
2693    }
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)]
2699pub struct UnwindTableRow<T, S = StoreOnHeap>
2700where
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
2711impl<T, S> Debug for UnwindTableRow<T, S>
2712where
2713    T: ReaderOffset,
2714    S: UnwindContextStorage<T>,
2715{
2716    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2717        f.debug_struct("UnwindTableRow")
2718            .field("start_address", &self.start_address)
2719            .field("end_address", &self.end_address)
2720            .field("saved_args_size", &self.saved_args_size)
2721            .field("cfa", &self.cfa)
2722            .field("registers", &self.registers)
2723            .finish()
2724    }
2725}
2726
2727impl<T, S> Clone for UnwindTableRow<T, S>
2728where
2729    T: ReaderOffset,
2730    S: UnwindContextStorage<T>,
2731{
2732    fn clone(&self) -> Self {
2733        Self {
2734            start_address: self.start_address,
2735            end_address: self.end_address,
2736            saved_args_size: self.saved_args_size,
2737            cfa: self.cfa.clone(),
2738            registers: self.registers.clone(),
2739        }
2740    }
2741}
2742
2743impl<T, S> Default for UnwindTableRow<T, S>
2744where
2745    T: ReaderOffset,
2746    S: UnwindContextStorage<T>,
2747{
2748    fn default() -> Self {
2749        UnwindTableRow {
2750            start_address: 0,
2751            end_address: 0,
2752            saved_args_size: 0,
2753            cfa: Default::default(),
2754            registers: Default::default(),
2755        }
2756    }
2757}
2758
2759impl<T, S> UnwindTableRow<T, S>
2760where
2761    T: ReaderOffset,
2762    S: UnwindContextStorage<T>,
2763{
2764    fn is_default(&self) -> bool {
2765        self.start_address == 0
2766            && self.end_address == 0
2767            && self.cfa.is_default()
2768            && self.registers.is_default()
2769    }
2770
2771    /// Get the starting PC address that this row applies to.
2772    pub fn start_address(&self) -> u64 {
2773        self.start_address
2774    }
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    pub fn end_address(&self) -> u64 {
2784        self.end_address
2785    }
2786
2787    /// Return `true` if the given `address` is within this row's address range,
2788    /// `false` otherwise.
2789    pub fn contains(&self, address: u64) -> bool {
2790        self.start_address <= address && address < self.end_address
2791    }
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    pub fn saved_args_size(&self) -> u64 {
2798        self.saved_args_size
2799    }
2800
2801    /// Get the canonical frame address (CFA) recovery rule for this row.
2802    pub fn cfa(&self) -> &CfaRule<T> {
2803        &self.cfa
2804    }
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    pub fn register(&self, register: Register) -> RegisterRule<T> {
2851        self.registers.get(register)
2852    }
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    pub fn registers(&self) -> RegisterRuleIter<'_, T> {
2870        self.registers.iter()
2871    }
2872}
2873
2874/// The canonical frame address (CFA) recovery rules.
2875#[derive(Clone, Debug, PartialEq, Eq)]
2876pub 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
2888impl<T: ReaderOffset> Default for CfaRule<T> {
2889    fn default() -> Self {
2890        CfaRule::RegisterAndOffset {
2891            register: Register(0),
2892            offset: 0,
2893        }
2894    }
2895}
2896
2897impl<T: ReaderOffset> CfaRule<T> {
2898    fn is_default(&self) -> bool {
2899        match *self {
2900            CfaRule::RegisterAndOffset { register, offset } => {
2901                register == Register(0) && offset == 0
2902            }
2903            _ => false,
2904        }
2905    }
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]
2916pub 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
2953impl<T: ReaderOffset> RegisterRule<T> {
2954    fn is_defined(&self) -> bool {
2955        !matches!(*self, RegisterRule::Undefined)
2956    }
2957}
2958
2959/// A parsed call frame instruction.
2960#[derive(Clone, Debug, PartialEq, Eq)]
2961pub 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
3257const CFI_INSTRUCTION_HIGH_BITS_MASK: u8 = 0b1100_0000;
3258const CFI_INSTRUCTION_LOW_BITS_MASK: u8 = !CFI_INSTRUCTION_HIGH_BITS_MASK;
3259
3260impl<T: ReaderOffset> CallFrameInstruction<T> {
3261    fn parse<R: Reader<Offset = T>>(
3262        input: &mut R,
3263        address_encoding: Option<DwEhPe>,
3264        parameters: &PointerEncodingParameters<'_, R>,
3265        vendor: Vendor,
3266    ) -> Result<CallFrameInstruction<T>> {
3267        let instruction = input.read_u8()?;
3268        let high_bits = instruction & CFI_INSTRUCTION_HIGH_BITS_MASK;
3269
3270        if high_bits == constants::DW_CFA_advance_loc.0 {
3271            let delta = instruction & CFI_INSTRUCTION_LOW_BITS_MASK;
3272            return Ok(CallFrameInstruction::AdvanceLoc {
3273                delta: u32::from(delta),
3274            });
3275        }
3276
3277        if high_bits == constants::DW_CFA_offset.0 {
3278            let register = Register((instruction & CFI_INSTRUCTION_LOW_BITS_MASK).into());
3279            let offset = input.read_uleb128()?;
3280            return Ok(CallFrameInstruction::Offset {
3281                register,
3282                factored_offset: offset,
3283            });
3284        }
3285
3286        if high_bits == constants::DW_CFA_restore.0 {
3287            let register = Register((instruction & CFI_INSTRUCTION_LOW_BITS_MASK).into());
3288            return Ok(CallFrameInstruction::Restore { register });
3289        }
3290
3291        debug_assert_eq!(high_bits, 0);
3292        let instruction = constants::DwCfa(instruction);
3293
3294        match instruction {
3295            constants::DW_CFA_nop => Ok(CallFrameInstruction::Nop),
3296
3297            constants::DW_CFA_set_loc => {
3298                let address = if let Some(encoding) = address_encoding {
3299                    parse_encoded_pointer(encoding, parameters, input)?.direct()?
3300                } else {
3301                    input.read_address(parameters.address_size)?
3302                };
3303                Ok(CallFrameInstruction::SetLoc { address })
3304            }
3305
3306            constants::DW_CFA_advance_loc1 => {
3307                let delta = input.read_u8()?;
3308                Ok(CallFrameInstruction::AdvanceLoc {
3309                    delta: u32::from(delta),
3310                })
3311            }
3312
3313            constants::DW_CFA_advance_loc2 => {
3314                let delta = input.read_u16()?;
3315                Ok(CallFrameInstruction::AdvanceLoc {
3316                    delta: u32::from(delta),
3317                })
3318            }
3319
3320            constants::DW_CFA_advance_loc4 => {
3321                let delta = input.read_u32()?;
3322                Ok(CallFrameInstruction::AdvanceLoc { delta })
3323            }
3324
3325            constants::DW_CFA_offset_extended => {
3326                let register = input.read_uleb128().and_then(Register::from_u64)?;
3327                let offset = input.read_uleb128()?;
3328                Ok(CallFrameInstruction::Offset {
3329                    register,
3330                    factored_offset: offset,
3331                })
3332            }
3333
3334            constants::DW_CFA_restore_extended => {
3335                let register = input.read_uleb128().and_then(Register::from_u64)?;
3336                Ok(CallFrameInstruction::Restore { register })
3337            }
3338
3339            constants::DW_CFA_undefined => {
3340                let register = input.read_uleb128().and_then(Register::from_u64)?;
3341                Ok(CallFrameInstruction::Undefined { register })
3342            }
3343
3344            constants::DW_CFA_same_value => {
3345                let register = input.read_uleb128().and_then(Register::from_u64)?;
3346                Ok(CallFrameInstruction::SameValue { register })
3347            }
3348
3349            constants::DW_CFA_register => {
3350                let dest = input.read_uleb128().and_then(Register::from_u64)?;
3351                let src = input.read_uleb128().and_then(Register::from_u64)?;
3352                Ok(CallFrameInstruction::Register {
3353                    dest_register: dest,
3354                    src_register: src,
3355                })
3356            }
3357
3358            constants::DW_CFA_remember_state => Ok(CallFrameInstruction::RememberState),
3359
3360            constants::DW_CFA_restore_state => Ok(CallFrameInstruction::RestoreState),
3361
3362            constants::DW_CFA_def_cfa => {
3363                let register = input.read_uleb128().and_then(Register::from_u64)?;
3364                let offset = input.read_uleb128()?;
3365                Ok(CallFrameInstruction::DefCfa { register, offset })
3366            }
3367
3368            constants::DW_CFA_def_cfa_register => {
3369                let register = input.read_uleb128().and_then(Register::from_u64)?;
3370                Ok(CallFrameInstruction::DefCfaRegister { register })
3371            }
3372
3373            constants::DW_CFA_def_cfa_offset => {
3374                let offset = input.read_uleb128()?;
3375                Ok(CallFrameInstruction::DefCfaOffset { offset })
3376            }
3377
3378            constants::DW_CFA_def_cfa_expression => {
3379                let length = input.read_uleb128().and_then(R::Offset::from_u64)?;
3380                let offset = input.offset_from(parameters.section);
3381                input.skip(length)?;
3382                Ok(CallFrameInstruction::DefCfaExpression {
3383                    expression: UnwindExpression { offset, length },
3384                })
3385            }
3386
3387            constants::DW_CFA_expression => {
3388                let register = input.read_uleb128().and_then(Register::from_u64)?;
3389                let length = input.read_uleb128().and_then(R::Offset::from_u64)?;
3390                let offset = input.offset_from(parameters.section);
3391                input.skip(length)?;
3392                Ok(CallFrameInstruction::Expression {
3393                    register,
3394                    expression: UnwindExpression { offset, length },
3395                })
3396            }
3397
3398            constants::DW_CFA_offset_extended_sf => {
3399                let register = input.read_uleb128().and_then(Register::from_u64)?;
3400                let offset = input.read_sleb128()?;
3401                Ok(CallFrameInstruction::OffsetExtendedSf {
3402                    register,
3403                    factored_offset: offset,
3404                })
3405            }
3406
3407            constants::DW_CFA_def_cfa_sf => {
3408                let register = input.read_uleb128().and_then(Register::from_u64)?;
3409                let offset = input.read_sleb128()?;
3410                Ok(CallFrameInstruction::DefCfaSf {
3411                    register,
3412                    factored_offset: offset,
3413                })
3414            }
3415
3416            constants::DW_CFA_def_cfa_offset_sf => {
3417                let offset = input.read_sleb128()?;
3418                Ok(CallFrameInstruction::DefCfaOffsetSf {
3419                    factored_offset: offset,
3420                })
3421            }
3422
3423            constants::DW_CFA_val_offset => {
3424                let register = input.read_uleb128().and_then(Register::from_u64)?;
3425                let offset = input.read_uleb128()?;
3426                Ok(CallFrameInstruction::ValOffset {
3427                    register,
3428                    factored_offset: offset,
3429                })
3430            }
3431
3432            constants::DW_CFA_val_offset_sf => {
3433                let register = input.read_uleb128().and_then(Register::from_u64)?;
3434                let offset = input.read_sleb128()?;
3435                Ok(CallFrameInstruction::ValOffsetSf {
3436                    register,
3437                    factored_offset: offset,
3438                })
3439            }
3440
3441            constants::DW_CFA_val_expression => {
3442                let register = input.read_uleb128().and_then(Register::from_u64)?;
3443                let length = input.read_uleb128().and_then(R::Offset::from_u64)?;
3444                let offset = input.offset_from(parameters.section);
3445                input.skip(length)?;
3446                Ok(CallFrameInstruction::ValExpression {
3447                    register,
3448                    expression: UnwindExpression { offset, length },
3449                })
3450            }
3451
3452            constants::DW_CFA_GNU_args_size => {
3453                let size = input.read_uleb128()?;
3454                Ok(CallFrameInstruction::ArgsSize { size })
3455            }
3456
3457            constants::DW_CFA_AARCH64_negate_ra_state if vendor == Vendor::AArch64 => {
3458                Ok(CallFrameInstruction::NegateRaState)
3459            }
3460
3461            otherwise => Err(Error::UnknownCallFrameInstruction(otherwise)),
3462        }
3463    }
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)]
3471pub struct CallFrameInstructionIter<'a, R: Reader> {
3472    input: R,
3473    address_encoding: Option<constants::DwEhPe>,
3474    parameters: PointerEncodingParameters<'a, R>,
3475    vendor: Vendor,
3476}
3477
3478impl<'a, R: Reader> CallFrameInstructionIter<'a, R> {
3479    /// Parse the next call frame instruction.
3480    pub fn next(&mut self) -> Result<Option<CallFrameInstruction<R::Offset>>> {
3481        if self.input.is_empty() {
3482            return Ok(None);
3483        }
3484
3485        match CallFrameInstruction::parse(
3486            &mut self.input,
3487            self.address_encoding,
3488            &self.parameters,
3489            self.vendor,
3490        ) {
3491            Ok(instruction) => Ok(Some(instruction)),
3492            Err(e) => {
3493                self.input.empty();
3494                Err(e)
3495            }
3496        }
3497    }
3498}
3499
3500#[cfg(feature = "fallible-iterator")]
3501impl<'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)]
3537pub 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
3544impl<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    pub fn get<R, S>(&self, section: &S) -> Result<Expression<R>>
3550    where
3551        R: Reader<Offset = T>,
3552        S: UnwindSection<R>,
3553    {
3554        let input = &mut section.section().clone();
3555        input.skip(self.offset)?;
3556        let data = input.split(self.length)?;
3557        Ok(Expression(data))
3558    }
3559}
3560
3561/// Parse a `DW_EH_PE_*` pointer encoding.
3562#[doc(hidden)]
3563#[inline]
3564fn parse_pointer_encoding<R: Reader>(input: &mut R) -> Result<constants::DwEhPe> {
3565    let eh_pe = input.read_u8()?;
3566    let eh_pe = constants::DwEhPe(eh_pe);
3567
3568    if eh_pe.is_valid_encoding() {
3569        Ok(eh_pe)
3570    } else {
3571        Err(Error::UnknownPointerEncoding(eh_pe))
3572    }
3573}
3574
3575/// A decoded pointer.
3576#[derive(Copy, Clone, Debug, PartialEq, Eq)]
3577pub 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
3590impl Default for Pointer {
3591    #[inline]
3592    fn default() -> Self {
3593        Pointer::Direct(0)
3594    }
3595}
3596
3597impl Pointer {
3598    #[inline]
3599    fn new(encoding: constants::DwEhPe, address: u64) -> Pointer {
3600        if encoding.is_indirect() {
3601            Pointer::Indirect(address)
3602        } else {
3603            Pointer::Direct(address)
3604        }
3605    }
3606
3607    /// Return the direct pointer value.
3608    #[inline]
3609    pub fn direct(self) -> Result<u64> {
3610        match self {
3611            Pointer::Direct(p) => Ok(p),
3612            Pointer::Indirect(_) => Err(Error::UnsupportedPointerEncoding),
3613        }
3614    }
3615
3616    /// Return the pointer value, discarding indirectness information.
3617    #[inline]
3618    pub fn pointer(self) -> u64 {
3619        match self {
3620            Pointer::Direct(p) | Pointer::Indirect(p) => p,
3621        }
3622    }
3623}
3624
3625#[derive(Clone, Debug)]
3626struct PointerEncodingParameters<'a, R: Reader> {
3627    bases: &'a SectionBaseAddresses,
3628    func_base: Option<u64>,
3629    address_size: u8,
3630    section: &'a R,
3631}
3632
3633fn parse_encoded_pointer<R: Reader>(
3634    encoding: constants::DwEhPe,
3635    parameters: &PointerEncodingParameters<'_, R>,
3636    input: &mut R,
3637) -> Result<Pointer> {
3638    // TODO: check this once only in parse_pointer_encoding
3639    if !encoding.is_valid_encoding() {
3640        return Err(Error::UnknownPointerEncoding(encoding));
3641    }
3642
3643    if encoding == constants::DW_EH_PE_omit {
3644        return Err(Error::CannotParseOmitPointerEncoding);
3645    }
3646
3647    let base = match encoding.application() {
3648        constants::DW_EH_PE_absptr => 0,
3649        constants::DW_EH_PE_pcrel => {
3650            if let Some(section_base) = parameters.bases.section {
3651                let offset_from_section = input.offset_from(parameters.section);
3652                section_base
3653                    .wrapping_add_sized(offset_from_section.into_u64(), parameters.address_size)
3654            } else {
3655                return Err(Error::PcRelativePointerButSectionBaseIsUndefined);
3656            }
3657        }
3658        constants::DW_EH_PE_textrel => {
3659            if let Some(text) = parameters.bases.text {
3660                text
3661            } else {
3662                return Err(Error::TextRelativePointerButTextBaseIsUndefined);
3663            }
3664        }
3665        constants::DW_EH_PE_datarel => {
3666            if let Some(data) = parameters.bases.data {
3667                data
3668            } else {
3669                return Err(Error::DataRelativePointerButDataBaseIsUndefined);
3670            }
3671        }
3672        constants::DW_EH_PE_funcrel => {
3673            if let Some(func) = parameters.func_base {
3674                func
3675            } else {
3676                return Err(Error::FuncRelativePointerInBadContext);
3677            }
3678        }
3679        constants::DW_EH_PE_aligned => return Err(Error::UnsupportedPointerEncoding),
3680        _ => unreachable!(),
3681    };
3682
3683    let offset = parse_encoded_value(encoding, parameters, input)?;
3684    Ok(Pointer::new(
3685        encoding,
3686        base.wrapping_add_sized(offset, parameters.address_size),
3687    ))
3688}
3689
3690fn parse_encoded_value<R: Reader>(
3691    encoding: constants::DwEhPe,
3692    parameters: &PointerEncodingParameters<'_, R>,
3693    input: &mut R,
3694) -> Result<u64> {
3695    match encoding.format() {
3696        // Unsigned variants.
3697        constants::DW_EH_PE_absptr => input.read_address(parameters.address_size),
3698        constants::DW_EH_PE_uleb128 => input.read_uleb128(),
3699        constants::DW_EH_PE_udata2 => input.read_u16().map(u64::from),
3700        constants::DW_EH_PE_udata4 => input.read_u32().map(u64::from),
3701        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        constants::DW_EH_PE_sleb128 => input.read_sleb128().map(|a| a as u64),
3708        constants::DW_EH_PE_sdata2 => input.read_i16().map(|a| a as u64),
3709        constants::DW_EH_PE_sdata4 => input.read_i32().map(|a| a as u64),
3710        constants::DW_EH_PE_sdata8 => input.read_i64().map(|a| a as u64),
3711
3712        // That was all of the valid encoding formats.
3713        _ => unreachable!(),
3714    }
3715}
3716
3717#[cfg(test)]
3718mod 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}