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