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#[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    pub fn set_address_size(&mut self, address_size: u8) {
48        self.address_size = address_size
49    }
50
51    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    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        DebugFrame {
97            section,
98            address_size: mem::size_of::<usize>() as u8,
99            vendor: Vendor::Default,
100        }
101    }
102}
103
104#[derive(Clone, Copy, Debug, PartialEq, Eq)]
109pub struct EhFrameHdr<R: Reader>(R);
110
111#[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    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    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        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, ¶meters, &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, ¶meters, &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    pub fn eh_frame_ptr(&self) -> Pointer {
200        self.eh_frame_ptr
201    }
202
203    pub fn table(&self) -> Option<EhHdrTable<'_, R>> {
205        if self.fde_count == 0 {
215            None
216        } else {
217            Some(EhHdrTable { hdr: self })
218        }
219    }
220}
221
222#[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    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, ¶meters, &mut self.table)?;
252        let to = parse_encoded_pointer(self.hdr.table_enc, ¶meters, &mut self.table)?;
253        Ok(Some((from, to)))
254    }
255    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#[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    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    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, ¶meters, &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, ¶meters, &mut reader)
374    }
375
376    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        R::Offset::from_u64(ptr - eh_frame_ptr).map(EhFrameOffset)
385    }
386
387    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    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#[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    pub fn set_address_size(&mut self, address_size: u8) {
499        self.address_size = address_size
500    }
501
502    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    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        EhFrame {
548            section,
549            address_size: mem::size_of::<usize>() as u8,
550            vendor: Vendor::Default,
551        }
552    }
553}
554
555#[doc(hidden)]
558#[allow(missing_docs)]
559#[derive(Clone, Copy, Debug, PartialEq, Eq)]
560pub enum CieOffsetEncoding {
561    U32,
562    U64,
563}
564
565pub trait UnwindOffset<T = usize>: Copy + Debug + Eq + From<T>
569where
570    T: ReaderOffset,
571{
572    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#[doc(hidden)]
600pub trait _UnwindSectionPrivate<R: Reader> {
601    fn section(&self) -> &R;
603
604    fn has_zero_terminator() -> bool;
606
607    fn is_cie(format: Format, id: u64) -> bool;
609
610    fn cie_offset_encoding(format: Format) -> CieOffsetEncoding;
613
614    fn resolve_cie_offset(&self, base: R::Offset, offset: R::Offset) -> Option<R::Offset>;
620
621    fn has_address_and_segment_sizes(version: u8) -> bool;
624
625    fn address_size(&self) -> u8;
627
628    fn vendor(&self) -> Vendor;
630}
631
632pub trait UnwindSection<R: Reader>: Clone + Debug + _UnwindSectionPrivate<R> {
636    type Offset: UnwindOffset<R::Offset>;
639
640    fn entries<'bases>(&self, bases: &'bases BaseAddresses) -> CfiEntriesIter<'bases, Self, R> {
646        CfiEntriesIter {
647            section: self.clone(),
648            bases,
649            input: self.section().clone(),
650        }
651    }
652
653    fn cie_from_offset(
655        &self,
656        bases: &BaseAddresses,
657        offset: Self::Offset,
658    ) -> Result<CommonInformationEntry<R>> {
659        let offset = UnwindOffset::into(offset);
660        let input = &mut self.section().clone();
661        input.skip(offset)?;
662        CommonInformationEntry::parse(bases, self, input)
663    }
664
665    fn partial_fde_from_offset<'bases>(
667        &self,
668        bases: &'bases BaseAddresses,
669        offset: Self::Offset,
670    ) -> Result<PartialFrameDescriptionEntry<'bases, Self, R>> {
671        let offset = UnwindOffset::into(offset);
672        let input = &mut self.section().clone();
673        input.skip(offset)?;
674        PartialFrameDescriptionEntry::parse_partial(self, bases, input)
675    }
676
677    fn fde_from_offset<F>(
679        &self,
680        bases: &BaseAddresses,
681        offset: Self::Offset,
682        get_cie: F,
683    ) -> Result<FrameDescriptionEntry<R>>
684    where
685        F: FnMut(&Self, &BaseAddresses, Self::Offset) -> Result<CommonInformationEntry<R>>,
686    {
687        let partial = self.partial_fde_from_offset(bases, offset)?;
688        partial.parse(get_cie)
689    }
690
691    fn fde_for_address<F>(
703        &self,
704        bases: &BaseAddresses,
705        address: u64,
706        mut get_cie: F,
707    ) -> Result<FrameDescriptionEntry<R>>
708    where
709        F: FnMut(&Self, &BaseAddresses, Self::Offset) -> Result<CommonInformationEntry<R>>,
710    {
711        let mut entries = self.entries(bases);
712        while let Some(entry) = entries.next()? {
713            match entry {
714                CieOrFde::Cie(_) => {}
715                CieOrFde::Fde(partial) => {
716                    let fde = partial.parse(&mut get_cie)?;
717                    if fde.contains(address) {
718                        return Ok(fde);
719                    }
720                }
721            }
722        }
723        Err(Error::NoUnwindInfoForAddress)
724    }
725
726    #[inline]
772    fn unwind_info_for_address<'ctx, F, S>(
773        &self,
774        bases: &BaseAddresses,
775        ctx: &'ctx mut UnwindContext<R::Offset, S>,
776        address: u64,
777        get_cie: F,
778    ) -> Result<&'ctx UnwindTableRow<R::Offset, S>>
779    where
780        F: FnMut(&Self, &BaseAddresses, Self::Offset) -> Result<CommonInformationEntry<R>>,
781        S: UnwindContextStorage<R::Offset>,
782    {
783        let fde = self.fde_for_address(bases, address, get_cie)?;
784        fde.unwind_info_for_address(self, bases, ctx, address)
785    }
786}
787
788impl<R: Reader> _UnwindSectionPrivate<R> for DebugFrame<R> {
789    fn section(&self) -> &R {
790        &self.section
791    }
792
793    fn has_zero_terminator() -> bool {
794        false
795    }
796
797    fn is_cie(format: Format, id: u64) -> bool {
798        match format {
799            Format::Dwarf32 => id == 0xffff_ffff,
800            Format::Dwarf64 => id == 0xffff_ffff_ffff_ffff,
801        }
802    }
803
804    fn cie_offset_encoding(format: Format) -> CieOffsetEncoding {
805        match format {
806            Format::Dwarf32 => CieOffsetEncoding::U32,
807            Format::Dwarf64 => CieOffsetEncoding::U64,
808        }
809    }
810
811    fn resolve_cie_offset(&self, _: R::Offset, offset: R::Offset) -> Option<R::Offset> {
812        Some(offset)
813    }
814
815    fn has_address_and_segment_sizes(version: u8) -> bool {
816        version == 4
817    }
818
819    fn address_size(&self) -> u8 {
820        self.address_size
821    }
822
823    fn vendor(&self) -> Vendor {
824        self.vendor
825    }
826}
827
828impl<R: Reader> UnwindSection<R> for DebugFrame<R> {
829    type Offset = DebugFrameOffset<R::Offset>;
830}
831
832impl<R: Reader> _UnwindSectionPrivate<R> for EhFrame<R> {
833    fn section(&self) -> &R {
834        &self.section
835    }
836
837    fn has_zero_terminator() -> bool {
838        true
839    }
840
841    fn is_cie(_: Format, id: u64) -> bool {
842        id == 0
843    }
844
845    fn cie_offset_encoding(_format: Format) -> CieOffsetEncoding {
846        CieOffsetEncoding::U32
849    }
850
851    fn resolve_cie_offset(&self, base: R::Offset, offset: R::Offset) -> Option<R::Offset> {
852        base.checked_sub(offset)
853    }
854
855    fn has_address_and_segment_sizes(_version: u8) -> bool {
856        false
857    }
858
859    fn address_size(&self) -> u8 {
860        self.address_size
861    }
862
863    fn vendor(&self) -> Vendor {
864        self.vendor
865    }
866}
867
868impl<R: Reader> UnwindSection<R> for EhFrame<R> {
869    type Offset = EhFrameOffset<R::Offset>;
870}
871
872#[derive(Clone, Default, Debug, PartialEq, Eq)]
895pub struct BaseAddresses {
896    pub eh_frame_hdr: SectionBaseAddresses,
898
899    pub eh_frame: SectionBaseAddresses,
901}
902
903#[derive(Clone, Default, Debug, PartialEq, Eq)]
908pub struct SectionBaseAddresses {
909    pub section: Option<u64>,
911
912    pub text: Option<u64>,
915
916    pub data: Option<u64>,
924}
925
926impl BaseAddresses {
927    #[inline]
929    pub fn set_eh_frame_hdr(mut self, addr: u64) -> Self {
930        self.eh_frame_hdr.section = Some(addr);
931        self.eh_frame_hdr.data = Some(addr);
932        self
933    }
934
935    #[inline]
937    pub fn set_eh_frame(mut self, addr: u64) -> Self {
938        self.eh_frame.section = Some(addr);
939        self
940    }
941
942    #[inline]
944    pub fn set_text(mut self, addr: u64) -> Self {
945        self.eh_frame_hdr.text = Some(addr);
946        self.eh_frame.text = Some(addr);
947        self
948    }
949
950    #[inline]
952    pub fn set_got(mut self, addr: u64) -> Self {
953        self.eh_frame.data = Some(addr);
954        self
955    }
956}
957
958#[derive(Clone, Debug)]
998pub struct CfiEntriesIter<'bases, Section, R>
999where
1000    R: Reader,
1001    Section: UnwindSection<R>,
1002{
1003    section: Section,
1004    bases: &'bases BaseAddresses,
1005    input: R,
1006}
1007
1008impl<'bases, Section, R> CfiEntriesIter<'bases, Section, R>
1009where
1010    R: Reader,
1011    Section: UnwindSection<R>,
1012{
1013    pub fn next(&mut self) -> Result<Option<CieOrFde<'bases, Section, R>>> {
1015        loop {
1016            if self.input.is_empty() {
1017                return Ok(None);
1018            }
1019
1020            match parse_cfi_entry(self.bases, &self.section, &mut self.input) {
1021                Ok(Some(entry)) => return Ok(Some(entry)),
1022                Err(e) => {
1023                    self.input.empty();
1024                    return Err(e);
1025                }
1026                Ok(None) => {
1027                    if Section::has_zero_terminator() {
1028                        self.input.empty();
1029                        return Ok(None);
1030                    }
1031
1032                    continue;
1037                }
1038            }
1039        }
1040    }
1041}
1042
1043#[cfg(feature = "fallible-iterator")]
1044impl<'bases, Section, R> fallible_iterator::FallibleIterator for CfiEntriesIter<'bases, Section, R>
1045where
1046    R: Reader,
1047    Section: UnwindSection<R>,
1048{
1049    type Item = CieOrFde<'bases, Section, R>;
1050    type Error = Error;
1051
1052    fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
1053        CfiEntriesIter::next(self)
1054    }
1055}
1056
1057#[derive(Clone, Debug, PartialEq, Eq)]
1059pub enum CieOrFde<'bases, Section, R>
1060where
1061    R: Reader,
1062    Section: UnwindSection<R>,
1063{
1064    Cie(CommonInformationEntry<R>),
1066    Fde(PartialFrameDescriptionEntry<'bases, Section, R>),
1070}
1071
1072fn parse_cfi_entry<'bases, Section, R>(
1073    bases: &'bases BaseAddresses,
1074    section: &Section,
1075    input: &mut R,
1076) -> Result<Option<CieOrFde<'bases, Section, R>>>
1077where
1078    R: Reader,
1079    Section: UnwindSection<R>,
1080{
1081    let offset = input.offset_from(section.section());
1082    let (length, format) = input.read_initial_length()?;
1083    if length.into_u64() == 0 {
1084        return Ok(None);
1085    }
1086
1087    let mut rest = input.split(length)?;
1088    let cie_offset_base = rest.offset_from(section.section());
1089    let cie_id_or_offset = match Section::cie_offset_encoding(format) {
1090        CieOffsetEncoding::U32 => rest.read_u32().map(u64::from)?,
1091        CieOffsetEncoding::U64 => rest.read_u64()?,
1092    };
1093
1094    if Section::is_cie(format, cie_id_or_offset) {
1095        let cie = CommonInformationEntry::parse_rest(offset, length, format, bases, section, rest)?;
1096        Ok(Some(CieOrFde::Cie(cie)))
1097    } else {
1098        let cie_offset = R::Offset::from_u64(cie_id_or_offset)?;
1099        let cie_offset = match section.resolve_cie_offset(cie_offset_base, cie_offset) {
1100            None => return Err(Error::OffsetOutOfBounds),
1101            Some(cie_offset) => cie_offset,
1102        };
1103
1104        let fde = PartialFrameDescriptionEntry {
1105            offset,
1106            length,
1107            format,
1108            cie_offset: cie_offset.into(),
1109            rest,
1110            section: section.clone(),
1111            bases,
1112        };
1113
1114        Ok(Some(CieOrFde::Fde(fde)))
1115    }
1116}
1117
1118#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
1122pub struct Augmentation {
1123    lsda: Option<constants::DwEhPe>,
1133
1134    personality: Option<(constants::DwEhPe, Pointer)>,
1142
1143    fde_address_encoding: Option<constants::DwEhPe>,
1149
1150    is_signal_trampoline: bool,
1152}
1153
1154impl Augmentation {
1155    fn parse<Section, R>(
1156        augmentation_str: &mut R,
1157        bases: &BaseAddresses,
1158        address_size: u8,
1159        section: &Section,
1160        input: &mut R,
1161    ) -> Result<Augmentation>
1162    where
1163        R: Reader,
1164        Section: UnwindSection<R>,
1165    {
1166        debug_assert!(
1167            !augmentation_str.is_empty(),
1168            "Augmentation::parse should only be called if we have an augmentation"
1169        );
1170
1171        let mut augmentation = Augmentation::default();
1172
1173        let mut parsed_first = false;
1174        let mut data = None;
1175
1176        while !augmentation_str.is_empty() {
1177            let ch = augmentation_str.read_u8()?;
1178            match ch {
1179                b'z' => {
1180                    if parsed_first {
1181                        return Err(Error::UnknownAugmentation);
1182                    }
1183
1184                    let augmentation_length = input.read_uleb128().and_then(R::Offset::from_u64)?;
1185                    data = Some(input.split(augmentation_length)?);
1186                }
1187                b'L' => {
1188                    let rest = data.as_mut().ok_or(Error::UnknownAugmentation)?;
1189                    let encoding = parse_pointer_encoding(rest)?;
1190                    augmentation.lsda = Some(encoding);
1191                }
1192                b'P' => {
1193                    let rest = data.as_mut().ok_or(Error::UnknownAugmentation)?;
1194                    let encoding = parse_pointer_encoding(rest)?;
1195                    let parameters = PointerEncodingParameters {
1196                        bases: &bases.eh_frame,
1197                        func_base: None,
1198                        address_size,
1199                        section: section.section(),
1200                    };
1201
1202                    let personality = parse_encoded_pointer(encoding, ¶meters, rest)?;
1203                    augmentation.personality = Some((encoding, personality));
1204                }
1205                b'R' => {
1206                    let rest = data.as_mut().ok_or(Error::UnknownAugmentation)?;
1207                    let encoding = parse_pointer_encoding(rest)?;
1208                    augmentation.fde_address_encoding = Some(encoding);
1209                }
1210                b'S' => augmentation.is_signal_trampoline = true,
1211                _ => return Err(Error::UnknownAugmentation),
1212            }
1213
1214            parsed_first = true;
1215        }
1216
1217        Ok(augmentation)
1218    }
1219}
1220
1221#[derive(Clone, Debug, Default, PartialEq, Eq)]
1223struct AugmentationData {
1224    lsda: Option<Pointer>,
1225}
1226
1227impl AugmentationData {
1228    fn parse<R: Reader>(
1229        augmentation: &Augmentation,
1230        encoding_parameters: &PointerEncodingParameters<'_, R>,
1231        input: &mut R,
1232    ) -> Result<AugmentationData> {
1233        let aug_data_len = input.read_uleb128().and_then(R::Offset::from_u64)?;
1240        let rest = &mut input.split(aug_data_len)?;
1241        let mut augmentation_data = AugmentationData::default();
1242        if let Some(encoding) = augmentation.lsda {
1243            let lsda = parse_encoded_pointer(encoding, encoding_parameters, rest)?;
1244            augmentation_data.lsda = Some(lsda);
1245        }
1246        Ok(augmentation_data)
1247    }
1248}
1249
1250#[derive(Clone, Debug, PartialEq, Eq)]
1254pub struct CommonInformationEntry<R, Offset = <R as Reader>::Offset>
1255where
1256    R: Reader<Offset = Offset>,
1257    Offset: ReaderOffset,
1258{
1259    offset: Offset,
1261
1262    length: Offset,
1267
1268    format: Format,
1269
1270    version: u8,
1273
1274    augmentation: Option<Augmentation>,
1276
1277    address_size: u8,
1281
1282    code_alignment_factor: u64,
1285
1286    data_alignment_factor: i64,
1289
1290    return_address_register: Register,
1294
1295    initial_instructions: R,
1306}
1307
1308impl<R: Reader> CommonInformationEntry<R> {
1309    fn parse<Section: UnwindSection<R>>(
1310        bases: &BaseAddresses,
1311        section: &Section,
1312        input: &mut R,
1313    ) -> Result<CommonInformationEntry<R>> {
1314        match parse_cfi_entry(bases, section, input)? {
1315            Some(CieOrFde::Cie(cie)) => Ok(cie),
1316            Some(CieOrFde::Fde(_)) => Err(Error::NotCieId),
1317            None => Err(Error::NoEntryAtGivenOffset),
1318        }
1319    }
1320
1321    fn parse_rest<Section: UnwindSection<R>>(
1322        offset: R::Offset,
1323        length: R::Offset,
1324        format: Format,
1325        bases: &BaseAddresses,
1326        section: &Section,
1327        mut rest: R,
1328    ) -> Result<CommonInformationEntry<R>> {
1329        let version = rest.read_u8()?;
1330
1331        match version {
1335            1 | 3 | 4 => (),
1336            _ => return Err(Error::UnknownVersion(u64::from(version))),
1337        }
1338
1339        let mut augmentation_string = rest.read_null_terminated_slice()?;
1340
1341        let address_size = if Section::has_address_and_segment_sizes(version) {
1342            let address_size = rest.read_address_size()?;
1343            let segment_size = rest.read_u8()?;
1344            if segment_size != 0 {
1345                return Err(Error::UnsupportedSegmentSize);
1346            }
1347            address_size
1348        } else {
1349            section.address_size()
1350        };
1351
1352        let code_alignment_factor = rest.read_uleb128()?;
1353        let data_alignment_factor = rest.read_sleb128()?;
1354
1355        let return_address_register = if version == 1 {
1356            Register(rest.read_u8()?.into())
1357        } else {
1358            rest.read_uleb128().and_then(Register::from_u64)?
1359        };
1360
1361        let augmentation = if augmentation_string.is_empty() {
1362            None
1363        } else {
1364            Some(Augmentation::parse(
1365                &mut augmentation_string,
1366                bases,
1367                address_size,
1368                section,
1369                &mut rest,
1370            )?)
1371        };
1372
1373        let entry = CommonInformationEntry {
1374            offset,
1375            length,
1376            format,
1377            version,
1378            augmentation,
1379            address_size,
1380            code_alignment_factor,
1381            data_alignment_factor,
1382            return_address_register,
1383            initial_instructions: rest,
1384        };
1385
1386        Ok(entry)
1387    }
1388}
1389
1390impl<R: Reader> CommonInformationEntry<R> {
1395    pub fn offset(&self) -> R::Offset {
1397        self.offset
1398    }
1399
1400    pub fn encoding(&self) -> Encoding {
1402        Encoding {
1403            format: self.format,
1404            version: u16::from(self.version),
1405            address_size: self.address_size,
1406        }
1407    }
1408
1409    pub fn address_size(&self) -> u8 {
1411        self.address_size
1412    }
1413
1414    pub fn instructions<'a, Section>(
1419        &self,
1420        section: &'a Section,
1421        bases: &'a BaseAddresses,
1422    ) -> CallFrameInstructionIter<'a, R>
1423    where
1424        Section: UnwindSection<R>,
1425    {
1426        CallFrameInstructionIter {
1427            input: self.initial_instructions.clone(),
1428            address_encoding: None,
1429            parameters: PointerEncodingParameters {
1430                bases: &bases.eh_frame,
1431                func_base: None,
1432                address_size: self.address_size,
1433                section: section.section(),
1434            },
1435            vendor: section.vendor(),
1436        }
1437    }
1438
1439    pub fn entry_len(&self) -> R::Offset {
1444        self.length
1445    }
1446
1447    pub fn version(&self) -> u8 {
1450        self.version
1451    }
1452
1453    pub fn augmentation(&self) -> Option<&Augmentation> {
1458        self.augmentation.as_ref()
1459    }
1460
1461    pub fn has_lsda(&self) -> bool {
1463        self.augmentation.map_or(false, |a| a.lsda.is_some())
1464    }
1465
1466    pub fn lsda_encoding(&self) -> Option<constants::DwEhPe> {
1468        self.augmentation.and_then(|a| a.lsda)
1469    }
1470
1471    pub fn personality_with_encoding(&self) -> Option<(constants::DwEhPe, Pointer)> {
1474        self.augmentation.as_ref().and_then(|a| a.personality)
1475    }
1476
1477    pub fn personality(&self) -> Option<Pointer> {
1480        self.augmentation
1481            .as_ref()
1482            .and_then(|a| a.personality)
1483            .map(|(_, p)| p)
1484    }
1485
1486    pub fn fde_address_encoding(&self) -> Option<constants::DwEhPe> {
1488        self.augmentation.and_then(|a| a.fde_address_encoding)
1489    }
1490
1491    pub fn is_signal_trampoline(&self) -> bool {
1493        self.augmentation.map_or(false, |a| a.is_signal_trampoline)
1494    }
1495
1496    pub fn code_alignment_factor(&self) -> u64 {
1499        self.code_alignment_factor
1500    }
1501
1502    pub fn data_alignment_factor(&self) -> i64 {
1505        self.data_alignment_factor
1506    }
1507
1508    pub fn return_address_register(&self) -> Register {
1512        self.return_address_register
1513    }
1514}
1515
1516#[derive(Clone, Debug, PartialEq, Eq)]
1520pub struct PartialFrameDescriptionEntry<'bases, Section, R>
1521where
1522    R: Reader,
1523    Section: UnwindSection<R>,
1524{
1525    offset: R::Offset,
1526    length: R::Offset,
1527    format: Format,
1528    cie_offset: Section::Offset,
1529    rest: R,
1530    section: Section,
1531    bases: &'bases BaseAddresses,
1532}
1533
1534impl<'bases, Section, R> PartialFrameDescriptionEntry<'bases, Section, R>
1535where
1536    R: Reader,
1537    Section: UnwindSection<R>,
1538{
1539    fn parse_partial(
1540        section: &Section,
1541        bases: &'bases BaseAddresses,
1542        input: &mut R,
1543    ) -> Result<PartialFrameDescriptionEntry<'bases, Section, R>> {
1544        match parse_cfi_entry(bases, section, input)? {
1545            Some(CieOrFde::Cie(_)) => Err(Error::NotFdePointer),
1546            Some(CieOrFde::Fde(partial)) => Ok(partial),
1547            None => Err(Error::NoEntryAtGivenOffset),
1548        }
1549    }
1550
1551    pub fn parse<F>(&self, get_cie: F) -> Result<FrameDescriptionEntry<R>>
1557    where
1558        F: FnMut(&Section, &BaseAddresses, Section::Offset) -> Result<CommonInformationEntry<R>>,
1559    {
1560        FrameDescriptionEntry::parse_rest(
1561            self.offset,
1562            self.length,
1563            self.format,
1564            self.cie_offset,
1565            self.rest.clone(),
1566            &self.section,
1567            self.bases,
1568            get_cie,
1569        )
1570    }
1571
1572    pub fn offset(&self) -> R::Offset {
1574        self.offset
1575    }
1576
1577    pub fn cie_offset(&self) -> Section::Offset {
1579        self.cie_offset
1580    }
1581
1582    pub fn entry_len(&self) -> R::Offset {
1587        self.length
1588    }
1589}
1590
1591#[derive(Clone, Debug, PartialEq, Eq)]
1593pub struct FrameDescriptionEntry<R, Offset = <R as Reader>::Offset>
1594where
1595    R: Reader<Offset = Offset>,
1596    Offset: ReaderOffset,
1597{
1598    offset: Offset,
1600
1601    length: Offset,
1606
1607    format: Format,
1608
1609    cie: CommonInformationEntry<R, Offset>,
1614
1615    initial_address: u64,
1619
1620    address_range: u64,
1622
1623    augmentation: Option<AugmentationData>,
1625
1626    instructions: R,
1631}
1632
1633impl<R: Reader> FrameDescriptionEntry<R> {
1634    fn parse_rest<Section, F>(
1635        offset: R::Offset,
1636        length: R::Offset,
1637        format: Format,
1638        cie_pointer: Section::Offset,
1639        mut rest: R,
1640        section: &Section,
1641        bases: &BaseAddresses,
1642        mut get_cie: F,
1643    ) -> Result<FrameDescriptionEntry<R>>
1644    where
1645        Section: UnwindSection<R>,
1646        F: FnMut(&Section, &BaseAddresses, Section::Offset) -> Result<CommonInformationEntry<R>>,
1647    {
1648        let cie = get_cie(section, bases, cie_pointer)?;
1649
1650        let mut parameters = PointerEncodingParameters {
1651            bases: &bases.eh_frame,
1652            func_base: None,
1653            address_size: cie.address_size,
1654            section: section.section(),
1655        };
1656
1657        let (initial_address, address_range) = Self::parse_addresses(&mut rest, &cie, ¶meters)?;
1658        parameters.func_base = Some(initial_address);
1659
1660        let aug_data = if let Some(ref augmentation) = cie.augmentation {
1661            Some(AugmentationData::parse(
1662                augmentation,
1663                ¶meters,
1664                &mut rest,
1665            )?)
1666        } else {
1667            None
1668        };
1669
1670        let entry = FrameDescriptionEntry {
1671            offset,
1672            length,
1673            format,
1674            cie,
1675            initial_address,
1676            address_range,
1677            augmentation: aug_data,
1678            instructions: rest,
1679        };
1680
1681        Ok(entry)
1682    }
1683
1684    fn parse_addresses(
1685        input: &mut R,
1686        cie: &CommonInformationEntry<R>,
1687        parameters: &PointerEncodingParameters<'_, R>,
1688    ) -> Result<(u64, u64)> {
1689        let encoding = cie.augmentation().and_then(|a| a.fde_address_encoding);
1690        if let Some(encoding) = encoding {
1691            let initial_address = parse_encoded_pointer(encoding, parameters, input)?.pointer();
1693            let address_range = parse_encoded_value(encoding, parameters, input)?;
1694            Ok((initial_address, address_range))
1695        } else {
1696            let initial_address = input.read_address(cie.address_size)?;
1697            let address_range = input.read_address(cie.address_size)?;
1698            Ok((initial_address, address_range))
1699        }
1700    }
1701
1702    #[inline]
1704    pub fn rows<'a, 'ctx, Section, S>(
1705        &self,
1706        section: &'a Section,
1707        bases: &'a BaseAddresses,
1708        ctx: &'ctx mut UnwindContext<R::Offset, S>,
1709    ) -> Result<UnwindTable<'a, 'ctx, R, S>>
1710    where
1711        Section: UnwindSection<R>,
1712        S: UnwindContextStorage<R::Offset>,
1713    {
1714        UnwindTable::new(section, bases, ctx, self)
1715    }
1716
1717    pub fn unwind_info_for_address<'ctx, Section, S>(
1724        &self,
1725        section: &Section,
1726        bases: &BaseAddresses,
1727        ctx: &'ctx mut UnwindContext<R::Offset, S>,
1728        address: u64,
1729    ) -> Result<&'ctx UnwindTableRow<R::Offset, S>>
1730    where
1731        Section: UnwindSection<R>,
1732        S: UnwindContextStorage<R::Offset>,
1733    {
1734        let mut table = self.rows(section, bases, ctx)?;
1735        while let Some(row) = table.next_row()? {
1736            if row.contains(address) {
1737                return Ok(table.ctx.row());
1738            }
1739        }
1740        Err(Error::NoUnwindInfoForAddress)
1741    }
1742}
1743
1744#[allow(clippy::len_without_is_empty)]
1749impl<R: Reader> FrameDescriptionEntry<R> {
1750    pub fn offset(&self) -> R::Offset {
1752        self.offset
1753    }
1754
1755    pub fn cie(&self) -> &CommonInformationEntry<R> {
1757        &self.cie
1758    }
1759
1760    pub fn entry_len(&self) -> R::Offset {
1765        self.length
1766    }
1767
1768    pub fn instructions<'a, Section>(
1776        &self,
1777        section: &'a Section,
1778        bases: &'a BaseAddresses,
1779    ) -> CallFrameInstructionIter<'a, R>
1780    where
1781        Section: UnwindSection<R>,
1782    {
1783        CallFrameInstructionIter {
1784            input: self.instructions.clone(),
1785            address_encoding: self.cie.augmentation().and_then(|a| a.fde_address_encoding),
1786            parameters: PointerEncodingParameters {
1787                bases: &bases.eh_frame,
1788                func_base: None,
1789                address_size: self.cie.address_size,
1790                section: section.section(),
1791            },
1792            vendor: section.vendor(),
1793        }
1794    }
1795
1796    pub fn initial_address(&self) -> u64 {
1798        self.initial_address
1799    }
1800
1801    pub fn end_address(&self) -> u64 {
1806        self.initial_address
1807            .wrapping_add_sized(self.address_range, self.cie.address_size)
1808    }
1809
1810    pub fn len(&self) -> u64 {
1813        self.address_range
1814    }
1815
1816    pub fn contains(&self, address: u64) -> bool {
1822        self.initial_address() <= address && address < self.end_address()
1823    }
1824
1825    pub fn lsda(&self) -> Option<Pointer> {
1828        self.augmentation.as_ref().and_then(|a| a.lsda)
1829    }
1830
1831    #[inline]
1833    pub fn is_signal_trampoline(&self) -> bool {
1834        self.cie().is_signal_trampoline()
1835    }
1836
1837    #[inline]
1841    pub fn personality(&self) -> Option<Pointer> {
1842        self.cie().personality()
1843    }
1844}
1845
1846#[cfg_attr(
1849    feature = "read",
1850    doc = "
1851Normally you would only need to use [`StoreOnHeap`], which places the stack
1852on the heap using [`Box`]. This is the default storage type parameter for [`UnwindContext`].
1853
1854You may want to supply your own storage type for one of the following reasons:
1855
1856  1. In rare cases you may run into failed unwinds due to the fixed stack size
1857     used by [`StoreOnHeap`], so you may want to try a larger `Box`. If denial
1858     of service is not a concern, then you could also try a `Vec`-based stack which
1859     can grow as needed.
1860  2. You may want to avoid heap allocations entirely. You can use a fixed-size
1861     stack with in-line arrays, which will place the entire storage in-line into
1862     [`UnwindContext`].
1863"
1864)]
1865pub trait UnwindContextStorage<T: ReaderOffset>: Sized {
1897    type Rules: ArrayLike<Item = (Register, RegisterRule<T>)>;
1901
1902    type Stack: ArrayLike<Item = UnwindTableRow<T, Self>>;
1904}
1905
1906#[cfg(feature = "read")]
1907const MAX_RULES: usize = 192;
1908#[cfg(feature = "read")]
1909const MAX_UNWIND_STACK_DEPTH: usize = 4;
1910
1911#[cfg(feature = "read")]
1912impl<T: ReaderOffset> UnwindContextStorage<T> for StoreOnHeap {
1913    type Rules = [(Register, RegisterRule<T>); MAX_RULES];
1914    type Stack = Box<[UnwindTableRow<T, Self>; MAX_UNWIND_STACK_DEPTH]>;
1915}
1916
1917#[derive(Clone, PartialEq, Eq)]
1951pub struct UnwindContext<T, S = StoreOnHeap>
1952where
1953    T: ReaderOffset,
1954    S: UnwindContextStorage<T>,
1955{
1956    stack: ArrayVec<S::Stack>,
1960
1961    initial_rule: Option<(Register, RegisterRule<T>)>,
1970
1971    is_initialized: bool,
1972}
1973
1974impl<T, S> Debug for UnwindContext<T, S>
1975where
1976    T: ReaderOffset,
1977    S: UnwindContextStorage<T>,
1978{
1979    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1980        f.debug_struct("UnwindContext")
1981            .field("stack", &self.stack)
1982            .field("initial_rule", &self.initial_rule)
1983            .field("is_initialized", &self.is_initialized)
1984            .finish()
1985    }
1986}
1987
1988impl<T, S> Default for UnwindContext<T, S>
1989where
1990    T: ReaderOffset,
1991    S: UnwindContextStorage<T>,
1992{
1993    fn default() -> Self {
1994        Self::new_in()
1995    }
1996}
1997
1998#[cfg(feature = "read")]
1999impl<T: ReaderOffset> UnwindContext<T> {
2000    pub fn new() -> Self {
2002        Self::new_in()
2003    }
2004}
2005
2006impl<T, S> UnwindContext<T, S>
2011where
2012    T: ReaderOffset,
2013    S: UnwindContextStorage<T>,
2014{
2015    pub fn new_in() -> Self {
2017        let mut ctx = UnwindContext {
2018            stack: Default::default(),
2019            initial_rule: None,
2020            is_initialized: false,
2021        };
2022        ctx.reset();
2023        ctx
2024    }
2025
2026    fn initialize<Section, R>(
2028        &mut self,
2029        section: &Section,
2030        bases: &BaseAddresses,
2031        cie: &CommonInformationEntry<R>,
2032    ) -> Result<()>
2033    where
2034        R: Reader<Offset = T>,
2035        Section: UnwindSection<R>,
2036    {
2037        self.reset();
2039
2040        let mut table = UnwindTable::new_for_cie(section, bases, self, cie);
2041        while table.next_row()?.is_some() {}
2042
2043        self.save_initial_rules()?;
2044        Ok(())
2045    }
2046
2047    fn reset(&mut self) {
2048        self.stack.clear();
2049        self.stack.try_push(UnwindTableRow::default()).unwrap();
2050        debug_assert!(self.stack[0].is_default());
2051        self.initial_rule = None;
2052        self.is_initialized = false;
2053    }
2054
2055    fn row(&self) -> &UnwindTableRow<T, S> {
2056        self.stack.last().unwrap()
2057    }
2058
2059    fn row_mut(&mut self) -> &mut UnwindTableRow<T, S> {
2060        self.stack.last_mut().unwrap()
2061    }
2062
2063    fn save_initial_rules(&mut self) -> Result<()> {
2064        debug_assert!(!self.is_initialized);
2065        self.initial_rule = match *self.stack.last().unwrap().registers.rules {
2066            [] => Some((Register(0), RegisterRule::Undefined)),
2069            [ref rule] => Some(rule.clone()),
2070            _ => {
2071                let rules = self.stack.last().unwrap().clone();
2072                self.stack
2073                    .try_insert(0, rules)
2074                    .map_err(|_| Error::StackFull)?;
2075                None
2076            }
2077        };
2078        self.is_initialized = true;
2079        Ok(())
2080    }
2081
2082    fn start_address(&self) -> u64 {
2083        self.row().start_address
2084    }
2085
2086    fn set_start_address(&mut self, start_address: u64) {
2087        let row = self.row_mut();
2088        row.start_address = start_address;
2089    }
2090
2091    fn set_register_rule(&mut self, register: Register, rule: RegisterRule<T>) -> Result<()> {
2092        let row = self.row_mut();
2093        row.registers.set(register, rule)
2094    }
2095
2096    fn get_initial_rule(&self, register: Register) -> Option<RegisterRule<T>> {
2099        if !self.is_initialized {
2100            return None;
2101        }
2102        Some(match self.initial_rule {
2103            None => self.stack[0].registers.get(register),
2104            Some((r, ref rule)) if r == register => rule.clone(),
2105            _ => RegisterRule::Undefined,
2106        })
2107    }
2108
2109    fn set_cfa(&mut self, cfa: CfaRule<T>) {
2110        self.row_mut().cfa = cfa;
2111    }
2112
2113    fn cfa_mut(&mut self) -> &mut CfaRule<T> {
2114        &mut self.row_mut().cfa
2115    }
2116
2117    fn push_row(&mut self) -> Result<()> {
2118        let new_row = self.row().clone();
2119        self.stack.try_push(new_row).map_err(|_| Error::StackFull)
2120    }
2121
2122    fn pop_row(&mut self) -> Result<()> {
2123        let min_size = if self.is_initialized && self.initial_rule.is_none() {
2124            2
2125        } else {
2126            1
2127        };
2128        if self.stack.len() <= min_size {
2129            return Err(Error::PopWithEmptyStack);
2130        }
2131        self.stack.pop().unwrap();
2132        Ok(())
2133    }
2134}
2135
2136#[derive(Debug)]
2193pub struct UnwindTable<'a, 'ctx, R, S = StoreOnHeap>
2194where
2195    R: Reader,
2196    S: UnwindContextStorage<R::Offset>,
2197{
2198    code_alignment_factor: Wrapping<u64>,
2199    data_alignment_factor: Wrapping<i64>,
2200    address_size: u8,
2201    next_start_address: u64,
2202    last_end_address: u64,
2203    returned_last_row: bool,
2204    current_row_valid: bool,
2205    instructions: CallFrameInstructionIter<'a, R>,
2206    ctx: &'ctx mut UnwindContext<R::Offset, S>,
2207}
2208
2209impl<'a, 'ctx, R, S> UnwindTable<'a, 'ctx, R, S>
2214where
2215    R: Reader,
2216    S: UnwindContextStorage<R::Offset>,
2217{
2218    pub fn new<Section: UnwindSection<R>>(
2221        section: &'a Section,
2222        bases: &'a BaseAddresses,
2223        ctx: &'ctx mut UnwindContext<R::Offset, S>,
2224        fde: &FrameDescriptionEntry<R>,
2225    ) -> Result<Self> {
2226        ctx.initialize(section, bases, fde.cie())?;
2227        Ok(Self::new_for_fde(section, bases, ctx, fde))
2228    }
2229
2230    fn new_for_fde<Section: UnwindSection<R>>(
2231        section: &'a Section,
2232        bases: &'a BaseAddresses,
2233        ctx: &'ctx mut UnwindContext<R::Offset, S>,
2234        fde: &FrameDescriptionEntry<R>,
2235    ) -> Self {
2236        assert!(ctx.stack.len() >= 1);
2237        UnwindTable {
2238            code_alignment_factor: Wrapping(fde.cie().code_alignment_factor()),
2239            data_alignment_factor: Wrapping(fde.cie().data_alignment_factor()),
2240            address_size: fde.cie().address_size,
2241            next_start_address: fde.initial_address(),
2242            last_end_address: fde.end_address(),
2243            returned_last_row: false,
2244            current_row_valid: false,
2245            instructions: fde.instructions(section, bases),
2246            ctx,
2247        }
2248    }
2249
2250    fn new_for_cie<Section: UnwindSection<R>>(
2251        section: &'a Section,
2252        bases: &'a BaseAddresses,
2253        ctx: &'ctx mut UnwindContext<R::Offset, S>,
2254        cie: &CommonInformationEntry<R>,
2255    ) -> Self {
2256        assert!(ctx.stack.len() >= 1);
2257        UnwindTable {
2258            code_alignment_factor: Wrapping(cie.code_alignment_factor()),
2259            data_alignment_factor: Wrapping(cie.data_alignment_factor()),
2260            address_size: cie.address_size,
2261            next_start_address: 0,
2262            last_end_address: 0,
2263            returned_last_row: false,
2264            current_row_valid: false,
2265            instructions: cie.instructions(section, bases),
2266            ctx,
2267        }
2268    }
2269
2270    pub fn next_row(&mut self) -> Result<Option<&UnwindTableRow<R::Offset, S>>> {
2276        assert!(self.ctx.stack.len() >= 1);
2277        self.ctx.set_start_address(self.next_start_address);
2278        self.current_row_valid = false;
2279
2280        loop {
2281            match self.instructions.next() {
2282                Err(e) => return Err(e),
2283
2284                Ok(None) => {
2285                    if self.returned_last_row {
2286                        return Ok(None);
2287                    }
2288
2289                    let row = self.ctx.row_mut();
2290                    row.end_address = self.last_end_address;
2291
2292                    self.returned_last_row = true;
2293                    self.current_row_valid = true;
2294                    return Ok(Some(row));
2295                }
2296
2297                Ok(Some(instruction)) => {
2298                    if self.evaluate(instruction)? {
2299                        self.current_row_valid = true;
2300                        return Ok(Some(self.ctx.row()));
2301                    }
2302                }
2303            };
2304        }
2305    }
2306
2307    pub fn into_current_row(self) -> Option<&'ctx UnwindTableRow<R::Offset, S>> {
2309        if self.current_row_valid {
2310            Some(self.ctx.row())
2311        } else {
2312            None
2313        }
2314    }
2315
2316    fn evaluate(&mut self, instruction: CallFrameInstruction<R::Offset>) -> Result<bool> {
2319        use crate::CallFrameInstruction::*;
2320
2321        match instruction {
2322            SetLoc { address } => {
2325                if address < self.ctx.start_address() {
2326                    return Err(Error::InvalidAddressRange);
2327                }
2328
2329                self.next_start_address = address;
2330                self.ctx.row_mut().end_address = self.next_start_address;
2331                return Ok(true);
2332            }
2333            AdvanceLoc { delta } => {
2334                let delta = Wrapping(u64::from(delta)) * self.code_alignment_factor;
2335                self.next_start_address = self
2336                    .ctx
2337                    .start_address()
2338                    .add_sized(delta.0, self.address_size)?;
2339                self.ctx.row_mut().end_address = self.next_start_address;
2340                return Ok(true);
2341            }
2342
2343            DefCfa { register, offset } => {
2345                self.ctx.set_cfa(CfaRule::RegisterAndOffset {
2346                    register,
2347                    offset: offset as i64,
2348                });
2349            }
2350            DefCfaSf {
2351                register,
2352                factored_offset,
2353            } => {
2354                let data_align = self.data_alignment_factor;
2355                self.ctx.set_cfa(CfaRule::RegisterAndOffset {
2356                    register,
2357                    offset: (Wrapping(factored_offset) * data_align).0,
2358                });
2359            }
2360            DefCfaRegister { register } => {
2361                if let CfaRule::RegisterAndOffset {
2362                    register: ref mut reg,
2363                    ..
2364                } = *self.ctx.cfa_mut()
2365                {
2366                    *reg = register;
2367                } else {
2368                    return Err(Error::CfiInstructionInInvalidContext);
2369                }
2370            }
2371            DefCfaOffset { offset } => {
2372                if let CfaRule::RegisterAndOffset {
2373                    offset: ref mut off,
2374                    ..
2375                } = *self.ctx.cfa_mut()
2376                {
2377                    *off = offset as i64;
2378                } else {
2379                    return Err(Error::CfiInstructionInInvalidContext);
2380                }
2381            }
2382            DefCfaOffsetSf { factored_offset } => {
2383                if let CfaRule::RegisterAndOffset {
2384                    offset: ref mut off,
2385                    ..
2386                } = *self.ctx.cfa_mut()
2387                {
2388                    let data_align = self.data_alignment_factor;
2389                    *off = (Wrapping(factored_offset) * data_align).0;
2390                } else {
2391                    return Err(Error::CfiInstructionInInvalidContext);
2392                }
2393            }
2394            DefCfaExpression { expression } => {
2395                self.ctx.set_cfa(CfaRule::Expression(expression));
2396            }
2397
2398            Undefined { register } => {
2400                self.ctx
2401                    .set_register_rule(register, RegisterRule::Undefined)?;
2402            }
2403            SameValue { register } => {
2404                self.ctx
2405                    .set_register_rule(register, RegisterRule::SameValue)?;
2406            }
2407            Offset {
2408                register,
2409                factored_offset,
2410            } => {
2411                let offset = Wrapping(factored_offset as i64) * self.data_alignment_factor;
2412                self.ctx
2413                    .set_register_rule(register, RegisterRule::Offset(offset.0))?;
2414            }
2415            OffsetExtendedSf {
2416                register,
2417                factored_offset,
2418            } => {
2419                let offset = Wrapping(factored_offset) * self.data_alignment_factor;
2420                self.ctx
2421                    .set_register_rule(register, RegisterRule::Offset(offset.0))?;
2422            }
2423            ValOffset {
2424                register,
2425                factored_offset,
2426            } => {
2427                let offset = Wrapping(factored_offset as i64) * self.data_alignment_factor;
2428                self.ctx
2429                    .set_register_rule(register, RegisterRule::ValOffset(offset.0))?;
2430            }
2431            ValOffsetSf {
2432                register,
2433                factored_offset,
2434            } => {
2435                let offset = Wrapping(factored_offset) * self.data_alignment_factor;
2436                self.ctx
2437                    .set_register_rule(register, RegisterRule::ValOffset(offset.0))?;
2438            }
2439            Register {
2440                dest_register,
2441                src_register,
2442            } => {
2443                self.ctx
2444                    .set_register_rule(dest_register, RegisterRule::Register(src_register))?;
2445            }
2446            Expression {
2447                register,
2448                expression,
2449            } => {
2450                let expression = RegisterRule::Expression(expression);
2451                self.ctx.set_register_rule(register, expression)?;
2452            }
2453            ValExpression {
2454                register,
2455                expression,
2456            } => {
2457                let expression = RegisterRule::ValExpression(expression);
2458                self.ctx.set_register_rule(register, expression)?;
2459            }
2460            Restore { register } => {
2461                let initial_rule = if let Some(rule) = self.ctx.get_initial_rule(register) {
2462                    rule
2463                } else {
2464                    return Err(Error::CfiInstructionInInvalidContext);
2467                };
2468
2469                self.ctx.set_register_rule(register, initial_rule)?;
2470            }
2471
2472            RememberState => {
2474                self.ctx.push_row()?;
2475            }
2476            RestoreState => {
2477                let start_address = self.ctx.start_address();
2479                self.ctx.pop_row()?;
2480                self.ctx.set_start_address(start_address);
2481            }
2482
2483            ArgsSize { size } => {
2486                self.ctx.row_mut().saved_args_size = size;
2487            }
2488
2489            NegateRaState => {
2491                let register = crate::AArch64::RA_SIGN_STATE;
2492                let value = match self.ctx.row().register(register) {
2493                    RegisterRule::Undefined => 0,
2494                    RegisterRule::Constant(value) => value,
2495                    _ => return Err(Error::CfiInstructionInInvalidContext),
2496                };
2497                self.ctx
2498                    .set_register_rule(register, RegisterRule::Constant(value ^ 1))?;
2499            }
2500
2501            Nop => {}
2503        };
2504
2505        Ok(false)
2506    }
2507}
2508
2509struct RegisterRuleMap<T, S = StoreOnHeap>
2531where
2532    T: ReaderOffset,
2533    S: UnwindContextStorage<T>,
2534{
2535    rules: ArrayVec<S::Rules>,
2536}
2537
2538impl<T, S> Debug for RegisterRuleMap<T, S>
2539where
2540    T: ReaderOffset,
2541    S: UnwindContextStorage<T>,
2542{
2543    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2544        f.debug_struct("RegisterRuleMap")
2545            .field("rules", &self.rules)
2546            .finish()
2547    }
2548}
2549
2550impl<T, S> Clone for RegisterRuleMap<T, S>
2551where
2552    T: ReaderOffset,
2553    S: UnwindContextStorage<T>,
2554{
2555    fn clone(&self) -> Self {
2556        Self {
2557            rules: self.rules.clone(),
2558        }
2559    }
2560}
2561
2562impl<T, S> Default for RegisterRuleMap<T, S>
2563where
2564    T: ReaderOffset,
2565    S: UnwindContextStorage<T>,
2566{
2567    fn default() -> Self {
2568        RegisterRuleMap {
2569            rules: Default::default(),
2570        }
2571    }
2572}
2573
2574impl<T, S> RegisterRuleMap<T, S>
2579where
2580    T: ReaderOffset,
2581    S: UnwindContextStorage<T>,
2582{
2583    fn is_default(&self) -> bool {
2584        self.rules.is_empty()
2585    }
2586
2587    fn get(&self, register: Register) -> RegisterRule<T> {
2588        self.rules
2589            .iter()
2590            .find(|rule| rule.0 == register)
2591            .map(|r| {
2592                debug_assert!(r.1.is_defined());
2593                r.1.clone()
2594            })
2595            .unwrap_or(RegisterRule::Undefined)
2596    }
2597
2598    fn set(&mut self, register: Register, rule: RegisterRule<T>) -> Result<()> {
2599        if !rule.is_defined() {
2600            let idx = self
2601                .rules
2602                .iter()
2603                .enumerate()
2604                .find(|&(_, r)| r.0 == register)
2605                .map(|(i, _)| i);
2606            if let Some(idx) = idx {
2607                self.rules.swap_remove(idx);
2608            }
2609            return Ok(());
2610        }
2611
2612        for &mut (reg, ref mut old_rule) in &mut *self.rules {
2613            debug_assert!(old_rule.is_defined());
2614            if reg == register {
2615                *old_rule = rule;
2616                return Ok(());
2617            }
2618        }
2619
2620        self.rules
2621            .try_push((register, rule))
2622            .map_err(|_| Error::TooManyRegisterRules)
2623    }
2624
2625    fn iter(&self) -> RegisterRuleIter<'_, T> {
2626        RegisterRuleIter(self.rules.iter())
2627    }
2628}
2629
2630impl<'a, R, S> FromIterator<&'a (Register, RegisterRule<R>)> for RegisterRuleMap<R, S>
2631where
2632    R: 'a + ReaderOffset,
2633    S: UnwindContextStorage<R>,
2634{
2635    fn from_iter<T>(iter: T) -> Self
2636    where
2637        T: IntoIterator<Item = &'a (Register, RegisterRule<R>)>,
2638    {
2639        let iter = iter.into_iter();
2640        let mut rules = RegisterRuleMap::default();
2641        for &(reg, ref rule) in iter.filter(|r| r.1.is_defined()) {
2642            rules.set(reg, rule.clone()).expect(
2643                "This is only used in tests, impl isn't exposed publicly.
2644                         If you trip this, fix your test",
2645            );
2646        }
2647        rules
2648    }
2649}
2650
2651impl<T, S> PartialEq for RegisterRuleMap<T, S>
2652where
2653    T: ReaderOffset + PartialEq,
2654    S: UnwindContextStorage<T>,
2655{
2656    fn eq(&self, rhs: &Self) -> bool {
2657        for &(reg, ref rule) in &*self.rules {
2658            debug_assert!(rule.is_defined());
2659            if *rule != rhs.get(reg) {
2660                return false;
2661            }
2662        }
2663
2664        for &(reg, ref rhs_rule) in &*rhs.rules {
2665            debug_assert!(rhs_rule.is_defined());
2666            if *rhs_rule != self.get(reg) {
2667                return false;
2668            }
2669        }
2670
2671        true
2672    }
2673}
2674
2675impl<T, S> Eq for RegisterRuleMap<T, S>
2676where
2677    T: ReaderOffset + Eq,
2678    S: UnwindContextStorage<T>,
2679{
2680}
2681
2682#[derive(Debug, Clone)]
2684pub struct RegisterRuleIter<'iter, T>(::core::slice::Iter<'iter, (Register, RegisterRule<T>)>)
2685where
2686    T: ReaderOffset;
2687
2688impl<'iter, T: ReaderOffset> Iterator for RegisterRuleIter<'iter, T> {
2689    type Item = &'iter (Register, RegisterRule<T>);
2690
2691    fn next(&mut self) -> Option<Self::Item> {
2692        self.0.next()
2693    }
2694}
2695
2696#[derive(PartialEq, Eq)]
2699pub struct UnwindTableRow<T, S = StoreOnHeap>
2700where
2701    T: ReaderOffset,
2702    S: UnwindContextStorage<T>,
2703{
2704    start_address: u64,
2705    end_address: u64,
2706    saved_args_size: u64,
2707    cfa: CfaRule<T>,
2708    registers: RegisterRuleMap<T, S>,
2709}
2710
2711impl<T, S> Debug for UnwindTableRow<T, S>
2712where
2713    T: ReaderOffset,
2714    S: UnwindContextStorage<T>,
2715{
2716    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2717        f.debug_struct("UnwindTableRow")
2718            .field("start_address", &self.start_address)
2719            .field("end_address", &self.end_address)
2720            .field("saved_args_size", &self.saved_args_size)
2721            .field("cfa", &self.cfa)
2722            .field("registers", &self.registers)
2723            .finish()
2724    }
2725}
2726
2727impl<T, S> Clone for UnwindTableRow<T, S>
2728where
2729    T: ReaderOffset,
2730    S: UnwindContextStorage<T>,
2731{
2732    fn clone(&self) -> Self {
2733        Self {
2734            start_address: self.start_address,
2735            end_address: self.end_address,
2736            saved_args_size: self.saved_args_size,
2737            cfa: self.cfa.clone(),
2738            registers: self.registers.clone(),
2739        }
2740    }
2741}
2742
2743impl<T, S> Default for UnwindTableRow<T, S>
2744where
2745    T: ReaderOffset,
2746    S: UnwindContextStorage<T>,
2747{
2748    fn default() -> Self {
2749        UnwindTableRow {
2750            start_address: 0,
2751            end_address: 0,
2752            saved_args_size: 0,
2753            cfa: Default::default(),
2754            registers: Default::default(),
2755        }
2756    }
2757}
2758
2759impl<T, S> UnwindTableRow<T, S>
2760where
2761    T: ReaderOffset,
2762    S: UnwindContextStorage<T>,
2763{
2764    fn is_default(&self) -> bool {
2765        self.start_address == 0
2766            && self.end_address == 0
2767            && self.cfa.is_default()
2768            && self.registers.is_default()
2769    }
2770
2771    pub fn start_address(&self) -> u64 {
2773        self.start_address
2774    }
2775
2776    pub fn end_address(&self) -> u64 {
2784        self.end_address
2785    }
2786
2787    pub fn contains(&self, address: u64) -> bool {
2790        self.start_address <= address && address < self.end_address
2791    }
2792
2793    pub fn saved_args_size(&self) -> u64 {
2798        self.saved_args_size
2799    }
2800
2801    pub fn cfa(&self) -> &CfaRule<T> {
2803        &self.cfa
2804    }
2805
2806    pub fn register(&self, register: Register) -> RegisterRule<T> {
2851        self.registers.get(register)
2852    }
2853
2854    pub fn registers(&self) -> RegisterRuleIter<'_, T> {
2870        self.registers.iter()
2871    }
2872}
2873
2874#[derive(Clone, Debug, PartialEq, Eq)]
2876pub enum CfaRule<T: ReaderOffset> {
2877    RegisterAndOffset {
2879        register: Register,
2881        offset: i64,
2883    },
2884    Expression(UnwindExpression<T>),
2886}
2887
2888impl<T: ReaderOffset> Default for CfaRule<T> {
2889    fn default() -> Self {
2890        CfaRule::RegisterAndOffset {
2891            register: Register(0),
2892            offset: 0,
2893        }
2894    }
2895}
2896
2897impl<T: ReaderOffset> CfaRule<T> {
2898    fn is_default(&self) -> bool {
2899        match *self {
2900            CfaRule::RegisterAndOffset { register, offset } => {
2901                register == Register(0) && offset == 0
2902            }
2903            _ => false,
2904        }
2905    }
2906}
2907
2908#[derive(Clone, Debug, PartialEq, Eq)]
2915#[non_exhaustive]
2916pub enum RegisterRule<T: ReaderOffset> {
2917    Undefined,
2920
2921    SameValue,
2925
2926    Offset(i64),
2929
2930    ValOffset(i64),
2933
2934    Register(Register),
2937
2938    Expression(UnwindExpression<T>),
2941
2942    ValExpression(UnwindExpression<T>),
2945
2946    Architectural,
2948
2949    Constant(u64),
2951}
2952
2953impl<T: ReaderOffset> RegisterRule<T> {
2954    fn is_defined(&self) -> bool {
2955        !matches!(*self, RegisterRule::Undefined)
2956    }
2957}
2958
2959#[derive(Clone, Debug, PartialEq, Eq)]
2961#[non_exhaustive]
2962pub enum CallFrameInstruction<T: ReaderOffset> {
2963    SetLoc {
2974        address: u64,
2976    },
2977
2978    AdvanceLoc {
2990        delta: u32,
2992    },
2993
2994    DefCfa {
3002        register: Register,
3004        offset: u64,
3006    },
3007
3008    DefCfaSf {
3016        register: Register,
3018        factored_offset: i64,
3020    },
3021
3022    DefCfaRegister {
3030        register: Register,
3032    },
3033
3034    DefCfaOffset {
3042        offset: u64,
3044    },
3045
3046    DefCfaOffsetSf {
3055        factored_offset: i64,
3057    },
3058
3059    DefCfaExpression {
3066        expression: UnwindExpression<T>,
3068    },
3069
3070    Undefined {
3077        register: Register,
3079    },
3080
3081    SameValue {
3087        register: Register,
3089    },
3090
3091    Offset {
3102        register: Register,
3104        factored_offset: u64,
3106    },
3107
3108    OffsetExtendedSf {
3117        register: Register,
3119        factored_offset: i64,
3121    },
3122
3123    ValOffset {
3131        register: Register,
3133        factored_offset: u64,
3135    },
3136
3137    ValOffsetSf {
3145        register: Register,
3147        factored_offset: i64,
3149    },
3150
3151    Register {
3158        dest_register: Register,
3160        src_register: Register,
3163    },
3164
3165    Expression {
3175        register: Register,
3177        expression: UnwindExpression<T>,
3179    },
3180
3181    ValExpression {
3192        register: Register,
3194        expression: UnwindExpression<T>,
3196    },
3197
3198    Restore {
3208        register: Register,
3210    },
3211
3212    RememberState,
3219
3220    RestoreState,
3226
3227    ArgsSize {
3235        size: u64,
3237    },
3238
3239    NegateRaState,
3249
3250    Nop,
3256}
3257
3258const CFI_INSTRUCTION_HIGH_BITS_MASK: u8 = 0b1100_0000;
3259const CFI_INSTRUCTION_LOW_BITS_MASK: u8 = !CFI_INSTRUCTION_HIGH_BITS_MASK;
3260
3261impl<T: ReaderOffset> CallFrameInstruction<T> {
3262    fn parse<R: Reader<Offset = T>>(
3263        input: &mut R,
3264        address_encoding: Option<DwEhPe>,
3265        parameters: &PointerEncodingParameters<'_, R>,
3266        vendor: Vendor,
3267    ) -> Result<CallFrameInstruction<T>> {
3268        let instruction = input.read_u8()?;
3269        let high_bits = instruction & CFI_INSTRUCTION_HIGH_BITS_MASK;
3270
3271        if high_bits == constants::DW_CFA_advance_loc.0 {
3272            let delta = instruction & CFI_INSTRUCTION_LOW_BITS_MASK;
3273            return Ok(CallFrameInstruction::AdvanceLoc {
3274                delta: u32::from(delta),
3275            });
3276        }
3277
3278        if high_bits == constants::DW_CFA_offset.0 {
3279            let register = Register((instruction & CFI_INSTRUCTION_LOW_BITS_MASK).into());
3280            let offset = input.read_uleb128()?;
3281            return Ok(CallFrameInstruction::Offset {
3282                register,
3283                factored_offset: offset,
3284            });
3285        }
3286
3287        if high_bits == constants::DW_CFA_restore.0 {
3288            let register = Register((instruction & CFI_INSTRUCTION_LOW_BITS_MASK).into());
3289            return Ok(CallFrameInstruction::Restore { register });
3290        }
3291
3292        debug_assert_eq!(high_bits, 0);
3293        let instruction = constants::DwCfa(instruction);
3294
3295        match instruction {
3296            constants::DW_CFA_nop => Ok(CallFrameInstruction::Nop),
3297
3298            constants::DW_CFA_set_loc => {
3299                let address = if let Some(encoding) = address_encoding {
3300                    parse_encoded_pointer(encoding, parameters, input)?.direct()?
3301                } else {
3302                    input.read_address(parameters.address_size)?
3303                };
3304                Ok(CallFrameInstruction::SetLoc { address })
3305            }
3306
3307            constants::DW_CFA_advance_loc1 => {
3308                let delta = input.read_u8()?;
3309                Ok(CallFrameInstruction::AdvanceLoc {
3310                    delta: u32::from(delta),
3311                })
3312            }
3313
3314            constants::DW_CFA_advance_loc2 => {
3315                let delta = input.read_u16()?;
3316                Ok(CallFrameInstruction::AdvanceLoc {
3317                    delta: u32::from(delta),
3318                })
3319            }
3320
3321            constants::DW_CFA_advance_loc4 => {
3322                let delta = input.read_u32()?;
3323                Ok(CallFrameInstruction::AdvanceLoc { delta })
3324            }
3325
3326            constants::DW_CFA_offset_extended => {
3327                let register = input.read_uleb128().and_then(Register::from_u64)?;
3328                let offset = input.read_uleb128()?;
3329                Ok(CallFrameInstruction::Offset {
3330                    register,
3331                    factored_offset: offset,
3332                })
3333            }
3334
3335            constants::DW_CFA_restore_extended => {
3336                let register = input.read_uleb128().and_then(Register::from_u64)?;
3337                Ok(CallFrameInstruction::Restore { register })
3338            }
3339
3340            constants::DW_CFA_undefined => {
3341                let register = input.read_uleb128().and_then(Register::from_u64)?;
3342                Ok(CallFrameInstruction::Undefined { register })
3343            }
3344
3345            constants::DW_CFA_same_value => {
3346                let register = input.read_uleb128().and_then(Register::from_u64)?;
3347                Ok(CallFrameInstruction::SameValue { register })
3348            }
3349
3350            constants::DW_CFA_register => {
3351                let dest = input.read_uleb128().and_then(Register::from_u64)?;
3352                let src = input.read_uleb128().and_then(Register::from_u64)?;
3353                Ok(CallFrameInstruction::Register {
3354                    dest_register: dest,
3355                    src_register: src,
3356                })
3357            }
3358
3359            constants::DW_CFA_remember_state => Ok(CallFrameInstruction::RememberState),
3360
3361            constants::DW_CFA_restore_state => Ok(CallFrameInstruction::RestoreState),
3362
3363            constants::DW_CFA_def_cfa => {
3364                let register = input.read_uleb128().and_then(Register::from_u64)?;
3365                let offset = input.read_uleb128()?;
3366                Ok(CallFrameInstruction::DefCfa { register, offset })
3367            }
3368
3369            constants::DW_CFA_def_cfa_register => {
3370                let register = input.read_uleb128().and_then(Register::from_u64)?;
3371                Ok(CallFrameInstruction::DefCfaRegister { register })
3372            }
3373
3374            constants::DW_CFA_def_cfa_offset => {
3375                let offset = input.read_uleb128()?;
3376                Ok(CallFrameInstruction::DefCfaOffset { offset })
3377            }
3378
3379            constants::DW_CFA_def_cfa_expression => {
3380                let length = input.read_uleb128().and_then(R::Offset::from_u64)?;
3381                let offset = input.offset_from(parameters.section);
3382                input.skip(length)?;
3383                Ok(CallFrameInstruction::DefCfaExpression {
3384                    expression: UnwindExpression { offset, length },
3385                })
3386            }
3387
3388            constants::DW_CFA_expression => {
3389                let register = input.read_uleb128().and_then(Register::from_u64)?;
3390                let length = input.read_uleb128().and_then(R::Offset::from_u64)?;
3391                let offset = input.offset_from(parameters.section);
3392                input.skip(length)?;
3393                Ok(CallFrameInstruction::Expression {
3394                    register,
3395                    expression: UnwindExpression { offset, length },
3396                })
3397            }
3398
3399            constants::DW_CFA_offset_extended_sf => {
3400                let register = input.read_uleb128().and_then(Register::from_u64)?;
3401                let offset = input.read_sleb128()?;
3402                Ok(CallFrameInstruction::OffsetExtendedSf {
3403                    register,
3404                    factored_offset: offset,
3405                })
3406            }
3407
3408            constants::DW_CFA_def_cfa_sf => {
3409                let register = input.read_uleb128().and_then(Register::from_u64)?;
3410                let offset = input.read_sleb128()?;
3411                Ok(CallFrameInstruction::DefCfaSf {
3412                    register,
3413                    factored_offset: offset,
3414                })
3415            }
3416
3417            constants::DW_CFA_def_cfa_offset_sf => {
3418                let offset = input.read_sleb128()?;
3419                Ok(CallFrameInstruction::DefCfaOffsetSf {
3420                    factored_offset: offset,
3421                })
3422            }
3423
3424            constants::DW_CFA_val_offset => {
3425                let register = input.read_uleb128().and_then(Register::from_u64)?;
3426                let offset = input.read_uleb128()?;
3427                Ok(CallFrameInstruction::ValOffset {
3428                    register,
3429                    factored_offset: offset,
3430                })
3431            }
3432
3433            constants::DW_CFA_val_offset_sf => {
3434                let register = input.read_uleb128().and_then(Register::from_u64)?;
3435                let offset = input.read_sleb128()?;
3436                Ok(CallFrameInstruction::ValOffsetSf {
3437                    register,
3438                    factored_offset: offset,
3439                })
3440            }
3441
3442            constants::DW_CFA_val_expression => {
3443                let register = input.read_uleb128().and_then(Register::from_u64)?;
3444                let length = input.read_uleb128().and_then(R::Offset::from_u64)?;
3445                let offset = input.offset_from(parameters.section);
3446                input.skip(length)?;
3447                Ok(CallFrameInstruction::ValExpression {
3448                    register,
3449                    expression: UnwindExpression { offset, length },
3450                })
3451            }
3452
3453            constants::DW_CFA_GNU_args_size => {
3454                let size = input.read_uleb128()?;
3455                Ok(CallFrameInstruction::ArgsSize { size })
3456            }
3457
3458            constants::DW_CFA_AARCH64_negate_ra_state if vendor == Vendor::AArch64 => {
3459                Ok(CallFrameInstruction::NegateRaState)
3460            }
3461
3462            otherwise => Err(Error::UnknownCallFrameInstruction(otherwise)),
3463        }
3464    }
3465}
3466
3467#[derive(Clone, Debug)]
3472pub struct CallFrameInstructionIter<'a, R: Reader> {
3473    input: R,
3474    address_encoding: Option<constants::DwEhPe>,
3475    parameters: PointerEncodingParameters<'a, R>,
3476    vendor: Vendor,
3477}
3478
3479impl<'a, R: Reader> CallFrameInstructionIter<'a, R> {
3480    pub fn next(&mut self) -> Result<Option<CallFrameInstruction<R::Offset>>> {
3482        if self.input.is_empty() {
3483            return Ok(None);
3484        }
3485
3486        match CallFrameInstruction::parse(
3487            &mut self.input,
3488            self.address_encoding,
3489            &self.parameters,
3490            self.vendor,
3491        ) {
3492            Ok(instruction) => Ok(Some(instruction)),
3493            Err(e) => {
3494                self.input.empty();
3495                Err(e)
3496            }
3497        }
3498    }
3499}
3500
3501#[cfg(feature = "fallible-iterator")]
3502impl<'a, R: Reader> fallible_iterator::FallibleIterator for CallFrameInstructionIter<'a, R> {
3503    type Item = CallFrameInstruction<R::Offset>;
3504    type Error = Error;
3505
3506    fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
3507        CallFrameInstructionIter::next(self)
3508    }
3509}
3510
3511#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3538pub struct UnwindExpression<T: ReaderOffset> {
3539    pub offset: T,
3541    pub length: T,
3543}
3544
3545impl<T: ReaderOffset> UnwindExpression<T> {
3546    pub fn get<R, S>(&self, section: &S) -> Result<Expression<R>>
3551    where
3552        R: Reader<Offset = T>,
3553        S: UnwindSection<R>,
3554    {
3555        let input = &mut section.section().clone();
3556        input.skip(self.offset)?;
3557        let data = input.split(self.length)?;
3558        Ok(Expression(data))
3559    }
3560}
3561
3562#[doc(hidden)]
3564#[inline]
3565fn parse_pointer_encoding<R: Reader>(input: &mut R) -> Result<constants::DwEhPe> {
3566    let eh_pe = input.read_u8()?;
3567    let eh_pe = constants::DwEhPe(eh_pe);
3568
3569    if eh_pe.is_valid_encoding() {
3570        Ok(eh_pe)
3571    } else {
3572        Err(Error::UnknownPointerEncoding(eh_pe))
3573    }
3574}
3575
3576#[derive(Copy, Clone, Debug, PartialEq, Eq)]
3578pub enum Pointer {
3579    Direct(u64),
3581
3582    Indirect(u64),
3589}
3590
3591impl Default for Pointer {
3592    #[inline]
3593    fn default() -> Self {
3594        Pointer::Direct(0)
3595    }
3596}
3597
3598impl Pointer {
3599    #[inline]
3600    fn new(encoding: constants::DwEhPe, address: u64) -> Pointer {
3601        if encoding.is_indirect() {
3602            Pointer::Indirect(address)
3603        } else {
3604            Pointer::Direct(address)
3605        }
3606    }
3607
3608    #[inline]
3610    pub fn direct(self) -> Result<u64> {
3611        match self {
3612            Pointer::Direct(p) => Ok(p),
3613            Pointer::Indirect(_) => Err(Error::UnsupportedPointerEncoding),
3614        }
3615    }
3616
3617    #[inline]
3619    pub fn pointer(self) -> u64 {
3620        match self {
3621            Pointer::Direct(p) | Pointer::Indirect(p) => p,
3622        }
3623    }
3624}
3625
3626#[derive(Clone, Debug)]
3627struct PointerEncodingParameters<'a, R: Reader> {
3628    bases: &'a SectionBaseAddresses,
3629    func_base: Option<u64>,
3630    address_size: u8,
3631    section: &'a R,
3632}
3633
3634fn parse_encoded_pointer<R: Reader>(
3635    encoding: constants::DwEhPe,
3636    parameters: &PointerEncodingParameters<'_, R>,
3637    input: &mut R,
3638) -> Result<Pointer> {
3639    if !encoding.is_valid_encoding() {
3641        return Err(Error::UnknownPointerEncoding(encoding));
3642    }
3643
3644    if encoding == constants::DW_EH_PE_omit {
3645        return Err(Error::CannotParseOmitPointerEncoding);
3646    }
3647
3648    let base = match encoding.application() {
3649        constants::DW_EH_PE_absptr => 0,
3650        constants::DW_EH_PE_pcrel => {
3651            if let Some(section_base) = parameters.bases.section {
3652                let offset_from_section = input.offset_from(parameters.section);
3653                section_base
3654                    .wrapping_add_sized(offset_from_section.into_u64(), parameters.address_size)
3655            } else {
3656                return Err(Error::PcRelativePointerButSectionBaseIsUndefined);
3657            }
3658        }
3659        constants::DW_EH_PE_textrel => {
3660            if let Some(text) = parameters.bases.text {
3661                text
3662            } else {
3663                return Err(Error::TextRelativePointerButTextBaseIsUndefined);
3664            }
3665        }
3666        constants::DW_EH_PE_datarel => {
3667            if let Some(data) = parameters.bases.data {
3668                data
3669            } else {
3670                return Err(Error::DataRelativePointerButDataBaseIsUndefined);
3671            }
3672        }
3673        constants::DW_EH_PE_funcrel => {
3674            if let Some(func) = parameters.func_base {
3675                func
3676            } else {
3677                return Err(Error::FuncRelativePointerInBadContext);
3678            }
3679        }
3680        constants::DW_EH_PE_aligned => return Err(Error::UnsupportedPointerEncoding),
3681        _ => unreachable!(),
3682    };
3683
3684    let offset = parse_encoded_value(encoding, parameters, input)?;
3685    Ok(Pointer::new(
3686        encoding,
3687        base.wrapping_add_sized(offset, parameters.address_size),
3688    ))
3689}
3690
3691fn parse_encoded_value<R: Reader>(
3692    encoding: constants::DwEhPe,
3693    parameters: &PointerEncodingParameters<'_, R>,
3694    input: &mut R,
3695) -> Result<u64> {
3696    match encoding.format() {
3697        constants::DW_EH_PE_absptr => input.read_address(parameters.address_size),
3699        constants::DW_EH_PE_uleb128 => input.read_uleb128(),
3700        constants::DW_EH_PE_udata2 => input.read_u16().map(u64::from),
3701        constants::DW_EH_PE_udata4 => input.read_u32().map(u64::from),
3702        constants::DW_EH_PE_udata8 => input.read_u64(),
3703
3704        constants::DW_EH_PE_sleb128 => input.read_sleb128().map(|a| a as u64),
3709        constants::DW_EH_PE_sdata2 => input.read_i16().map(|a| a as u64),
3710        constants::DW_EH_PE_sdata4 => input.read_i32().map(|a| a as u64),
3711        constants::DW_EH_PE_sdata8 => input.read_i64().map(|a| a as u64),
3712
3713        _ => unreachable!(),
3715    }
3716}
3717
3718#[cfg(test)]
3719mod tests {
3720    use super::*;
3721    use super::{parse_cfi_entry, AugmentationData, RegisterRuleMap, UnwindContext};
3722    use crate::common::Format;
3723    use crate::constants;
3724    use crate::endianity::{BigEndian, Endianity, LittleEndian, NativeEndian};
3725    use crate::read::{
3726        EndianSlice, Error, Pointer, ReaderOffsetId, Result, Section as ReadSection,
3727    };
3728    use crate::test_util::GimliSectionMethods;
3729    use alloc::boxed::Box;
3730    use alloc::vec::Vec;
3731    use core::marker::PhantomData;
3732    use core::mem;
3733    use test_assembler::{Endian, Label, LabelMaker, LabelOrNum, Section, ToLabelOrNum};
3734
3735    #[derive(Clone, Copy)]
3737    struct SectionKind<Section>(PhantomData<Section>);
3738
3739    impl<T> SectionKind<T> {
3740        fn endian<'input, E>(self) -> Endian
3741        where
3742            E: Endianity,
3743            T: UnwindSection<EndianSlice<'input, E>>,
3744            T::Offset: UnwindOffset<usize>,
3745        {
3746            if E::default().is_big_endian() {
3747                Endian::Big
3748            } else {
3749                Endian::Little
3750            }
3751        }
3752
3753        fn section<'input, E>(self, contents: &'input [u8]) -> T
3754        where
3755            E: Endianity,
3756            T: UnwindSection<EndianSlice<'input, E>> + ReadSection<EndianSlice<'input, E>>,
3757            T::Offset: UnwindOffset<usize>,
3758        {
3759            EndianSlice::new(contents, E::default()).into()
3760        }
3761    }
3762
3763    fn debug_frame_le<'a>() -> SectionKind<DebugFrame<EndianSlice<'a, LittleEndian>>> {
3764        SectionKind(PhantomData)
3765    }
3766
3767    fn debug_frame_be<'a>() -> SectionKind<DebugFrame<EndianSlice<'a, BigEndian>>> {
3768        SectionKind(PhantomData)
3769    }
3770
3771    fn eh_frame_le<'a>() -> SectionKind<EhFrame<EndianSlice<'a, LittleEndian>>> {
3772        SectionKind(PhantomData)
3773    }
3774
3775    fn parse_fde<Section, O, F, R>(
3776        section: Section,
3777        input: &mut R,
3778        get_cie: F,
3779    ) -> Result<FrameDescriptionEntry<R>>
3780    where
3781        R: Reader,
3782        Section: UnwindSection<R, Offset = O>,
3783        O: UnwindOffset<R::Offset>,
3784        F: FnMut(&Section, &BaseAddresses, O) -> Result<CommonInformationEntry<R>>,
3785    {
3786        let bases = Default::default();
3787        match parse_cfi_entry(&bases, §ion, input) {
3788            Ok(Some(CieOrFde::Fde(partial))) => partial.parse(get_cie),
3789            Ok(_) => Err(Error::NoEntryAtGivenOffset),
3790            Err(e) => Err(e),
3791        }
3792    }
3793
3794    trait CfiSectionMethods: GimliSectionMethods {
3797        fn cie<'aug, 'input, E, T>(
3798            self,
3799            _kind: SectionKind<T>,
3800            augmentation: Option<&'aug str>,
3801            cie: &mut CommonInformationEntry<EndianSlice<'input, E>>,
3802        ) -> Self
3803        where
3804            E: Endianity,
3805            T: UnwindSection<EndianSlice<'input, E>>,
3806            T::Offset: UnwindOffset;
3807        fn fde<'a, 'input, E, T, L>(
3808            self,
3809            _kind: SectionKind<T>,
3810            cie_offset: L,
3811            fde: &mut FrameDescriptionEntry<EndianSlice<'input, E>>,
3812        ) -> Self
3813        where
3814            E: Endianity,
3815            T: UnwindSection<EndianSlice<'input, E>>,
3816            T::Offset: UnwindOffset,
3817            L: ToLabelOrNum<'a, u64>;
3818    }
3819
3820    impl CfiSectionMethods for Section {
3821        fn cie<'aug, 'input, E, T>(
3822            self,
3823            _kind: SectionKind<T>,
3824            augmentation: Option<&'aug str>,
3825            cie: &mut CommonInformationEntry<EndianSlice<'input, E>>,
3826        ) -> Self
3827        where
3828            E: Endianity,
3829            T: UnwindSection<EndianSlice<'input, E>>,
3830            T::Offset: UnwindOffset,
3831        {
3832            cie.offset = self.size() as _;
3833            let length = Label::new();
3834            let start = Label::new();
3835            let end = Label::new();
3836
3837            let section = match cie.format {
3838                Format::Dwarf32 => self.D32(&length).mark(&start).D32(0xffff_ffff),
3839                Format::Dwarf64 => {
3840                    let section = self.D32(0xffff_ffff);
3841                    section.D64(&length).mark(&start).D64(0xffff_ffff_ffff_ffff)
3842                }
3843            };
3844
3845            let mut section = section.D8(cie.version);
3846
3847            if let Some(augmentation) = augmentation {
3848                section = section.append_bytes(augmentation.as_bytes());
3849            }
3850
3851            let section = section.D8(0);
3853
3854            let section = if T::has_address_and_segment_sizes(cie.version) {
3855                section.D8(cie.address_size).D8(0)
3856            } else {
3857                section
3858            };
3859
3860            let section = section
3861                .uleb(cie.code_alignment_factor)
3862                .sleb(cie.data_alignment_factor)
3863                .uleb(cie.return_address_register.0.into())
3864                .append_bytes(cie.initial_instructions.slice())
3865                .mark(&end);
3866
3867            cie.length = (&end - &start) as usize;
3868            length.set_const(cie.length as u64);
3869
3870            section
3871        }
3872
3873        fn fde<'a, 'input, E, T, L>(
3874            self,
3875            _kind: SectionKind<T>,
3876            cie_offset: L,
3877            fde: &mut FrameDescriptionEntry<EndianSlice<'input, E>>,
3878        ) -> Self
3879        where
3880            E: Endianity,
3881            T: UnwindSection<EndianSlice<'input, E>>,
3882            T::Offset: UnwindOffset,
3883            L: ToLabelOrNum<'a, u64>,
3884        {
3885            fde.offset = self.size() as _;
3886            let length = Label::new();
3887            let start = Label::new();
3888            let end = Label::new();
3889
3890            assert_eq!(fde.format, fde.cie.format);
3891
3892            let section = match T::cie_offset_encoding(fde.format) {
3893                CieOffsetEncoding::U32 => {
3894                    let section = self.D32(&length).mark(&start);
3895                    match cie_offset.to_labelornum() {
3896                        LabelOrNum::Label(ref l) => section.D32(l),
3897                        LabelOrNum::Num(o) => section.D32(o as u32),
3898                    }
3899                }
3900                CieOffsetEncoding::U64 => {
3901                    let section = self.D32(0xffff_ffff);
3902                    section.D64(&length).mark(&start).D64(cie_offset)
3903                }
3904            };
3905
3906            let section = match fde.cie.address_size {
3907                4 => section
3908                    .D32(fde.initial_address() as u32)
3909                    .D32(fde.len() as u32),
3910                8 => section.D64(fde.initial_address()).D64(fde.len()),
3911                x => panic!("Unsupported address size: {}", x),
3912            };
3913
3914            let section = if let Some(ref augmentation) = fde.augmentation {
3915                let cie_aug = fde
3916                    .cie
3917                    .augmentation
3918                    .expect("FDE has augmentation, but CIE doesn't");
3919
3920                if let Some(lsda) = augmentation.lsda {
3921                    assert_eq!(
3923                        cie_aug
3924                            .lsda
3925                            .expect("FDE has lsda, but CIE doesn't")
3926                            .format(),
3927                        constants::DW_EH_PE_absptr
3928                    );
3929
3930                    let section = section.uleb(u64::from(fde.cie.address_size));
3932                    match fde.cie.address_size {
3933                        4 => section.D32({
3934                            let x: u64 = lsda.pointer();
3935                            x as u32
3936                        }),
3937                        8 => section.D64({
3938                            let x: u64 = lsda.pointer();
3939                            x
3940                        }),
3941                        x => panic!("Unsupported address size: {}", x),
3942                    }
3943                } else {
3944                    section.uleb(0)
3947                }
3948            } else {
3949                section
3950            };
3951
3952            let section = section.append_bytes(fde.instructions.slice()).mark(&end);
3953
3954            fde.length = (&end - &start) as usize;
3955            length.set_const(fde.length as u64);
3956
3957            section
3958        }
3959    }
3960
3961    trait ResultExt {
3962        fn map_eof(self, input: &[u8]) -> Self;
3963    }
3964
3965    impl<T> ResultExt for Result<T> {
3966        fn map_eof(self, input: &[u8]) -> Self {
3967            match self {
3968                Err(Error::UnexpectedEof(id)) => {
3969                    let id = ReaderOffsetId(id.0 - input.as_ptr() as u64);
3970                    Err(Error::UnexpectedEof(id))
3971                }
3972                r => r,
3973            }
3974        }
3975    }
3976
3977    fn assert_parse_cie<'input, E>(
3978        kind: SectionKind<DebugFrame<EndianSlice<'input, E>>>,
3979        section: Section,
3980        address_size: u8,
3981        expected: Result<(
3982            EndianSlice<'input, E>,
3983            CommonInformationEntry<EndianSlice<'input, E>>,
3984        )>,
3985    ) where
3986        E: Endianity,
3987    {
3988        let section = section.get_contents().unwrap();
3989        let mut debug_frame = kind.section(§ion);
3990        debug_frame.set_address_size(address_size);
3991        let input = &mut EndianSlice::new(§ion, E::default());
3992        let bases = Default::default();
3993        let result = CommonInformationEntry::parse(&bases, &debug_frame, input);
3994        let result = result.map(|cie| (*input, cie)).map_eof(§ion);
3995        assert_eq!(result, expected);
3996    }
3997
3998    #[test]
3999    fn test_parse_cie_incomplete_length_32() {
4000        let kind = debug_frame_le();
4001        let section = Section::with_endian(kind.endian()).L16(5);
4002        assert_parse_cie(
4003            kind,
4004            section,
4005            8,
4006            Err(Error::UnexpectedEof(ReaderOffsetId(0))),
4007        );
4008    }
4009
4010    #[test]
4011    fn test_parse_cie_incomplete_length_64() {
4012        let kind = debug_frame_le();
4013        let section = Section::with_endian(kind.endian())
4014            .L32(0xffff_ffff)
4015            .L32(12345);
4016        assert_parse_cie(
4017            kind,
4018            section,
4019            8,
4020            Err(Error::UnexpectedEof(ReaderOffsetId(4))),
4021        );
4022    }
4023
4024    #[test]
4025    fn test_parse_cie_incomplete_id_32() {
4026        let kind = debug_frame_be();
4027        let section = Section::with_endian(kind.endian())
4028            .B32(3)
4030            .B32(0xffff_ffff);
4031        assert_parse_cie(
4032            kind,
4033            section,
4034            8,
4035            Err(Error::UnexpectedEof(ReaderOffsetId(4))),
4036        );
4037    }
4038
4039    #[test]
4040    fn test_parse_cie_bad_id_32() {
4041        let kind = debug_frame_be();
4042        let section = Section::with_endian(kind.endian())
4043            .B32(4)
4045            .B32(0xbad1_bad2);
4047        assert_parse_cie(kind, section, 8, Err(Error::NotCieId));
4048    }
4049
4050    #[test]
4051    fn test_parse_cie_32_bad_version() {
4052        let mut cie = CommonInformationEntry {
4053            offset: 0,
4054            length: 0,
4055            format: Format::Dwarf32,
4056            version: 99,
4057            augmentation: None,
4058            address_size: 4,
4059            code_alignment_factor: 1,
4060            data_alignment_factor: 2,
4061            return_address_register: Register(3),
4062            initial_instructions: EndianSlice::new(&[], LittleEndian),
4063        };
4064
4065        let kind = debug_frame_le();
4066        let section = Section::with_endian(kind.endian()).cie(kind, None, &mut cie);
4067        assert_parse_cie(kind, section, 4, Err(Error::UnknownVersion(99)));
4068    }
4069
4070    #[test]
4071    fn test_parse_cie_unknown_augmentation() {
4072        let length = Label::new();
4073        let start = Label::new();
4074        let end = Label::new();
4075
4076        let augmentation = "replicant";
4077        let expected_rest = [1, 2, 3];
4078
4079        let kind = debug_frame_le();
4080        let section = Section::with_endian(kind.endian())
4081            .L32(&length)
4083            .mark(&start)
4084            .L32(0xffff_ffff)
4086            .D8(4)
4088            .append_bytes(augmentation.as_bytes())
4090            .D8(0)
4092            .L32(1)
4094            .L32(2)
4095            .L32(3)
4096            .L32(4)
4097            .L32(5)
4098            .L32(6)
4099            .mark(&end)
4100            .append_bytes(&expected_rest);
4101
4102        let expected_length = (&end - &start) as u64;
4103        length.set_const(expected_length);
4104
4105        assert_parse_cie(kind, section, 8, Err(Error::UnknownAugmentation));
4106    }
4107
4108    fn test_parse_cie(format: Format, version: u8, address_size: u8) {
4109        let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9];
4110        let expected_instrs: Vec<_> = (0..4).map(|_| constants::DW_CFA_nop.0).collect();
4111
4112        let mut cie = CommonInformationEntry {
4113            offset: 0,
4114            length: 0,
4115            format,
4116            version,
4117            augmentation: None,
4118            address_size,
4119            code_alignment_factor: 16,
4120            data_alignment_factor: 32,
4121            return_address_register: Register(1),
4122            initial_instructions: EndianSlice::new(&expected_instrs, LittleEndian),
4123        };
4124
4125        let kind = debug_frame_le();
4126        let section = Section::with_endian(kind.endian())
4127            .cie(kind, None, &mut cie)
4128            .append_bytes(&expected_rest);
4129
4130        assert_parse_cie(
4131            kind,
4132            section,
4133            address_size,
4134            Ok((EndianSlice::new(&expected_rest, LittleEndian), cie)),
4135        );
4136    }
4137
4138    #[test]
4139    fn test_parse_cie_32_ok() {
4140        test_parse_cie(Format::Dwarf32, 1, 4);
4141        test_parse_cie(Format::Dwarf32, 1, 8);
4142        test_parse_cie(Format::Dwarf32, 4, 4);
4143        test_parse_cie(Format::Dwarf32, 4, 8);
4144    }
4145
4146    #[test]
4147    fn test_parse_cie_64_ok() {
4148        test_parse_cie(Format::Dwarf64, 1, 4);
4149        test_parse_cie(Format::Dwarf64, 1, 8);
4150        test_parse_cie(Format::Dwarf64, 4, 4);
4151        test_parse_cie(Format::Dwarf64, 4, 8);
4152    }
4153
4154    #[test]
4155    fn test_parse_cie_length_too_big() {
4156        let expected_instrs: Vec<_> = (0..13).map(|_| constants::DW_CFA_nop.0).collect();
4157
4158        let mut cie = CommonInformationEntry {
4159            offset: 0,
4160            length: 0,
4161            format: Format::Dwarf32,
4162            version: 4,
4163            augmentation: None,
4164            address_size: 4,
4165            code_alignment_factor: 0,
4166            data_alignment_factor: 0,
4167            return_address_register: Register(3),
4168            initial_instructions: EndianSlice::new(&expected_instrs, LittleEndian),
4169        };
4170
4171        let kind = debug_frame_le();
4172        let section = Section::with_endian(kind.endian()).cie(kind, None, &mut cie);
4173
4174        let mut contents = section.get_contents().unwrap();
4175
4176        contents[0] = 0;
4178        contents[1] = 0;
4179        contents[2] = 0;
4180        contents[3] = 255;
4181
4182        let debug_frame = DebugFrame::new(&contents, LittleEndian);
4183        let bases = Default::default();
4184        assert_eq!(
4185            CommonInformationEntry::parse(
4186                &bases,
4187                &debug_frame,
4188                &mut EndianSlice::new(&contents, LittleEndian)
4189            )
4190            .map_eof(&contents),
4191            Err(Error::UnexpectedEof(ReaderOffsetId(4)))
4192        );
4193    }
4194
4195    #[test]
4196    fn test_parse_fde_incomplete_length_32() {
4197        let kind = debug_frame_le();
4198        let section = Section::with_endian(kind.endian()).L16(5);
4199        let section = section.get_contents().unwrap();
4200        let debug_frame = kind.section(§ion);
4201        let rest = &mut EndianSlice::new(§ion, LittleEndian);
4202        assert_eq!(
4203            parse_fde(debug_frame, rest, UnwindSection::cie_from_offset).map_eof(§ion),
4204            Err(Error::UnexpectedEof(ReaderOffsetId(0)))
4205        );
4206    }
4207
4208    #[test]
4209    fn test_parse_fde_incomplete_length_64() {
4210        let kind = debug_frame_le();
4211        let section = Section::with_endian(kind.endian())
4212            .L32(0xffff_ffff)
4213            .L32(12345);
4214        let section = section.get_contents().unwrap();
4215        let debug_frame = kind.section(§ion);
4216        let rest = &mut EndianSlice::new(§ion, LittleEndian);
4217        assert_eq!(
4218            parse_fde(debug_frame, rest, UnwindSection::cie_from_offset).map_eof(§ion),
4219            Err(Error::UnexpectedEof(ReaderOffsetId(4)))
4220        );
4221    }
4222
4223    #[test]
4224    fn test_parse_fde_incomplete_cie_pointer_32() {
4225        let kind = debug_frame_be();
4226        let section = Section::with_endian(kind.endian())
4227            .B32(3)
4229            .B32(1994);
4230        let section = section.get_contents().unwrap();
4231        let debug_frame = kind.section(§ion);
4232        let rest = &mut EndianSlice::new(§ion, BigEndian);
4233        assert_eq!(
4234            parse_fde(debug_frame, rest, UnwindSection::cie_from_offset).map_eof(§ion),
4235            Err(Error::UnexpectedEof(ReaderOffsetId(4)))
4236        );
4237    }
4238
4239    #[test]
4240    fn test_parse_fde_32_ok() {
4241        let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9];
4242        let cie_offset = 0xbad0_bad1;
4243        let expected_instrs: Vec<_> = (0..7).map(|_| constants::DW_CFA_nop.0).collect();
4244
4245        let cie = CommonInformationEntry {
4246            offset: 0,
4247            length: 100,
4248            format: Format::Dwarf32,
4249            version: 4,
4250            augmentation: None,
4251            address_size: 8,
4253            code_alignment_factor: 3,
4254            data_alignment_factor: 2,
4255            return_address_register: Register(1),
4256            initial_instructions: EndianSlice::new(&[], LittleEndian),
4257        };
4258
4259        let mut fde = FrameDescriptionEntry {
4260            offset: 0,
4261            length: 0,
4262            format: Format::Dwarf32,
4263            cie: cie.clone(),
4264            initial_address: 0xfeed_beef,
4265            address_range: 39,
4266            augmentation: None,
4267            instructions: EndianSlice::new(&expected_instrs, LittleEndian),
4268        };
4269
4270        let kind = debug_frame_le();
4271        let section = Section::with_endian(kind.endian())
4272            .fde(kind, cie_offset, &mut fde)
4273            .append_bytes(&expected_rest);
4274
4275        let section = section.get_contents().unwrap();
4276        let debug_frame = kind.section(§ion);
4277        let rest = &mut EndianSlice::new(§ion, LittleEndian);
4278
4279        let get_cie = |_: &_, _: &_, offset| {
4280            assert_eq!(offset, DebugFrameOffset(cie_offset as usize));
4281            Ok(cie.clone())
4282        };
4283
4284        assert_eq!(parse_fde(debug_frame, rest, get_cie), Ok(fde));
4285        assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
4286    }
4287
4288    #[test]
4289    fn test_parse_fde_64_ok() {
4290        let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9];
4291        let cie_offset = 0xbad0_bad1;
4292        let expected_instrs: Vec<_> = (0..7).map(|_| constants::DW_CFA_nop.0).collect();
4293
4294        let cie = CommonInformationEntry {
4295            offset: 0,
4296            length: 100,
4297            format: Format::Dwarf64,
4298            version: 4,
4299            augmentation: None,
4300            address_size: 8,
4301            code_alignment_factor: 3,
4302            data_alignment_factor: 2,
4303            return_address_register: Register(1),
4304            initial_instructions: EndianSlice::new(&[], LittleEndian),
4305        };
4306
4307        let mut fde = FrameDescriptionEntry {
4308            offset: 0,
4309            length: 0,
4310            format: Format::Dwarf64,
4311            cie: cie.clone(),
4312            initial_address: 0xfeed_beef,
4313            address_range: 999,
4314            augmentation: None,
4315            instructions: EndianSlice::new(&expected_instrs, LittleEndian),
4316        };
4317
4318        let kind = debug_frame_le();
4319        let section = Section::with_endian(kind.endian())
4320            .fde(kind, cie_offset, &mut fde)
4321            .append_bytes(&expected_rest);
4322
4323        let section = section.get_contents().unwrap();
4324        let debug_frame = kind.section(§ion);
4325        let rest = &mut EndianSlice::new(§ion, LittleEndian);
4326
4327        let get_cie = |_: &_, _: &_, offset| {
4328            assert_eq!(offset, DebugFrameOffset(cie_offset as usize));
4329            Ok(cie.clone())
4330        };
4331
4332        assert_eq!(parse_fde(debug_frame, rest, get_cie), Ok(fde));
4333        assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
4334    }
4335
4336    #[test]
4337    fn test_parse_cfi_entry_on_cie_32_ok() {
4338        let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9];
4339        let expected_instrs: Vec<_> = (0..4).map(|_| constants::DW_CFA_nop.0).collect();
4340
4341        let mut cie = CommonInformationEntry {
4342            offset: 0,
4343            length: 0,
4344            format: Format::Dwarf32,
4345            version: 4,
4346            augmentation: None,
4347            address_size: 4,
4348            code_alignment_factor: 16,
4349            data_alignment_factor: 32,
4350            return_address_register: Register(1),
4351            initial_instructions: EndianSlice::new(&expected_instrs, BigEndian),
4352        };
4353
4354        let kind = debug_frame_be();
4355        let section = Section::with_endian(kind.endian())
4356            .cie(kind, None, &mut cie)
4357            .append_bytes(&expected_rest);
4358        let section = section.get_contents().unwrap();
4359        let debug_frame = kind.section(§ion);
4360        let rest = &mut EndianSlice::new(§ion, BigEndian);
4361
4362        let bases = Default::default();
4363        assert_eq!(
4364            parse_cfi_entry(&bases, &debug_frame, rest),
4365            Ok(Some(CieOrFde::Cie(cie)))
4366        );
4367        assert_eq!(*rest, EndianSlice::new(&expected_rest, BigEndian));
4368    }
4369
4370    #[test]
4371    fn test_parse_cfi_entry_on_fde_32_ok() {
4372        let cie_offset = 0x1234_5678;
4373        let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9];
4374        let expected_instrs: Vec<_> = (0..4).map(|_| constants::DW_CFA_nop.0).collect();
4375
4376        let cie = CommonInformationEntry {
4377            offset: 0,
4378            length: 0,
4379            format: Format::Dwarf32,
4380            version: 4,
4381            augmentation: None,
4382            address_size: 4,
4383            code_alignment_factor: 16,
4384            data_alignment_factor: 32,
4385            return_address_register: Register(1),
4386            initial_instructions: EndianSlice::new(&[], BigEndian),
4387        };
4388
4389        let mut fde = FrameDescriptionEntry {
4390            offset: 0,
4391            length: 0,
4392            format: Format::Dwarf32,
4393            cie: cie.clone(),
4394            initial_address: 0xfeed_beef,
4395            address_range: 39,
4396            augmentation: None,
4397            instructions: EndianSlice::new(&expected_instrs, BigEndian),
4398        };
4399
4400        let kind = debug_frame_be();
4401        let section = Section::with_endian(kind.endian())
4402            .fde(kind, cie_offset, &mut fde)
4403            .append_bytes(&expected_rest);
4404
4405        let section = section.get_contents().unwrap();
4406        let debug_frame = kind.section(§ion);
4407        let rest = &mut EndianSlice::new(§ion, BigEndian);
4408
4409        let bases = Default::default();
4410        match parse_cfi_entry(&bases, &debug_frame, rest) {
4411            Ok(Some(CieOrFde::Fde(partial))) => {
4412                assert_eq!(*rest, EndianSlice::new(&expected_rest, BigEndian));
4413
4414                assert_eq!(partial.length, fde.length);
4415                assert_eq!(partial.format, fde.format);
4416                assert_eq!(partial.cie_offset, DebugFrameOffset(cie_offset as usize));
4417
4418                let get_cie = |_: &_, _: &_, offset| {
4419                    assert_eq!(offset, DebugFrameOffset(cie_offset as usize));
4420                    Ok(cie.clone())
4421                };
4422
4423                assert_eq!(partial.parse(get_cie), Ok(fde));
4424            }
4425            otherwise => panic!("Unexpected result: {:#?}", otherwise),
4426        }
4427    }
4428
4429    #[test]
4430    fn test_cfi_entries_iter() {
4431        let expected_instrs1: Vec<_> = (0..4).map(|_| constants::DW_CFA_nop.0).collect();
4432
4433        let expected_instrs2: Vec<_> = (0..8).map(|_| constants::DW_CFA_nop.0).collect();
4434
4435        let expected_instrs3: Vec<_> = (0..12).map(|_| constants::DW_CFA_nop.0).collect();
4436
4437        let expected_instrs4: Vec<_> = (0..16).map(|_| constants::DW_CFA_nop.0).collect();
4438
4439        let mut cie1 = CommonInformationEntry {
4440            offset: 0,
4441            length: 0,
4442            format: Format::Dwarf32,
4443            version: 4,
4444            augmentation: None,
4445            address_size: 4,
4446            code_alignment_factor: 1,
4447            data_alignment_factor: 2,
4448            return_address_register: Register(3),
4449            initial_instructions: EndianSlice::new(&expected_instrs1, BigEndian),
4450        };
4451
4452        let mut cie2 = CommonInformationEntry {
4453            offset: 0,
4454            length: 0,
4455            format: Format::Dwarf32,
4456            version: 4,
4457            augmentation: None,
4458            address_size: 4,
4459            code_alignment_factor: 3,
4460            data_alignment_factor: 2,
4461            return_address_register: Register(1),
4462            initial_instructions: EndianSlice::new(&expected_instrs2, BigEndian),
4463        };
4464
4465        let cie1_location = Label::new();
4466        let cie2_location = Label::new();
4467
4468        let kind = debug_frame_be();
4472        let section = Section::with_endian(kind.endian())
4473            .mark(&cie1_location)
4474            .cie(kind, None, &mut cie1)
4475            .mark(&cie2_location)
4476            .cie(kind, None, &mut cie2);
4477
4478        let mut fde1 = FrameDescriptionEntry {
4479            offset: 0,
4480            length: 0,
4481            format: Format::Dwarf32,
4482            cie: cie1.clone(),
4483            initial_address: 0xfeed_beef,
4484            address_range: 39,
4485            augmentation: None,
4486            instructions: EndianSlice::new(&expected_instrs3, BigEndian),
4487        };
4488
4489        let mut fde2 = FrameDescriptionEntry {
4490            offset: 0,
4491            length: 0,
4492            format: Format::Dwarf32,
4493            cie: cie2.clone(),
4494            initial_address: 0xfeed_face,
4495            address_range: 9000,
4496            augmentation: None,
4497            instructions: EndianSlice::new(&expected_instrs4, BigEndian),
4498        };
4499
4500        let section =
4501            section
4502                .fde(kind, &cie1_location, &mut fde1)
4503                .fde(kind, &cie2_location, &mut fde2);
4504
4505        section.start().set_const(0);
4506
4507        let cie1_offset = cie1_location.value().unwrap() as usize;
4508        let cie2_offset = cie2_location.value().unwrap() as usize;
4509
4510        let contents = section.get_contents().unwrap();
4511        let debug_frame = kind.section(&contents);
4512
4513        let bases = Default::default();
4514        let mut entries = debug_frame.entries(&bases);
4515
4516        assert_eq!(entries.next(), Ok(Some(CieOrFde::Cie(cie1.clone()))));
4517        assert_eq!(entries.next(), Ok(Some(CieOrFde::Cie(cie2.clone()))));
4518
4519        match entries.next() {
4520            Ok(Some(CieOrFde::Fde(partial))) => {
4521                assert_eq!(partial.length, fde1.length);
4522                assert_eq!(partial.format, fde1.format);
4523                assert_eq!(partial.cie_offset, DebugFrameOffset(cie1_offset));
4524
4525                let get_cie = |_: &_, _: &_, offset| {
4526                    assert_eq!(offset, DebugFrameOffset(cie1_offset));
4527                    Ok(cie1.clone())
4528                };
4529                assert_eq!(partial.parse(get_cie), Ok(fde1));
4530            }
4531            otherwise => panic!("Unexpected result: {:#?}", otherwise),
4532        }
4533
4534        match entries.next() {
4535            Ok(Some(CieOrFde::Fde(partial))) => {
4536                assert_eq!(partial.length, fde2.length);
4537                assert_eq!(partial.format, fde2.format);
4538                assert_eq!(partial.cie_offset, DebugFrameOffset(cie2_offset));
4539
4540                let get_cie = |_: &_, _: &_, offset| {
4541                    assert_eq!(offset, DebugFrameOffset(cie2_offset));
4542                    Ok(cie2.clone())
4543                };
4544                assert_eq!(partial.parse(get_cie), Ok(fde2));
4545            }
4546            otherwise => panic!("Unexpected result: {:#?}", otherwise),
4547        }
4548
4549        assert_eq!(entries.next(), Ok(None));
4550    }
4551
4552    #[test]
4553    fn test_parse_cie_from_offset() {
4554        let filler = [1, 2, 3, 4, 5, 6, 7, 8, 9];
4555        let instrs: Vec<_> = (0..5).map(|_| constants::DW_CFA_nop.0).collect();
4556
4557        let mut cie = CommonInformationEntry {
4558            offset: 0,
4559            length: 0,
4560            format: Format::Dwarf64,
4561            version: 4,
4562            augmentation: None,
4563            address_size: 4,
4564            code_alignment_factor: 4,
4565            data_alignment_factor: 8,
4566            return_address_register: Register(12),
4567            initial_instructions: EndianSlice::new(&instrs, LittleEndian),
4568        };
4569
4570        let cie_location = Label::new();
4571
4572        let kind = debug_frame_le();
4573        let section = Section::with_endian(kind.endian())
4574            .append_bytes(&filler)
4575            .mark(&cie_location)
4576            .cie(kind, None, &mut cie)
4577            .append_bytes(&filler);
4578
4579        section.start().set_const(0);
4580
4581        let cie_offset = DebugFrameOffset(cie_location.value().unwrap() as usize);
4582
4583        let contents = section.get_contents().unwrap();
4584        let debug_frame = kind.section(&contents);
4585        let bases = Default::default();
4586
4587        assert_eq!(debug_frame.cie_from_offset(&bases, cie_offset), Ok(cie));
4588    }
4589
4590    fn parse_cfi_instruction<R: Reader + Default>(
4591        input: &mut R,
4592        address_size: u8,
4593    ) -> Result<CallFrameInstruction<R::Offset>> {
4594        let section = input.clone();
4595        let parameters = &PointerEncodingParameters {
4596            bases: &SectionBaseAddresses::default(),
4597            func_base: None,
4598            address_size,
4599            section: §ion,
4600        };
4601        CallFrameInstruction::parse(input, None, parameters, Vendor::Default)
4602    }
4603
4604    #[test]
4605    fn test_parse_cfi_instruction_advance_loc() {
4606        let expected_rest = [1, 2, 3, 4];
4607        let expected_delta = 42;
4608        let section = Section::with_endian(Endian::Little)
4609            .D8(constants::DW_CFA_advance_loc.0 | expected_delta)
4610            .append_bytes(&expected_rest);
4611        let contents = section.get_contents().unwrap();
4612        let input = &mut EndianSlice::new(&contents, LittleEndian);
4613        assert_eq!(
4614            parse_cfi_instruction(input, 8),
4615            Ok(CallFrameInstruction::AdvanceLoc {
4616                delta: u32::from(expected_delta),
4617            })
4618        );
4619        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4620    }
4621
4622    #[test]
4623    fn test_parse_cfi_instruction_offset() {
4624        let expected_rest = [1, 2, 3, 4];
4625        let expected_reg = 3;
4626        let expected_offset = 1997;
4627        let section = Section::with_endian(Endian::Little)
4628            .D8(constants::DW_CFA_offset.0 | expected_reg)
4629            .uleb(expected_offset)
4630            .append_bytes(&expected_rest);
4631        let contents = section.get_contents().unwrap();
4632        let input = &mut EndianSlice::new(&contents, LittleEndian);
4633        assert_eq!(
4634            parse_cfi_instruction(input, 8),
4635            Ok(CallFrameInstruction::Offset {
4636                register: Register(expected_reg.into()),
4637                factored_offset: expected_offset,
4638            })
4639        );
4640        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4641    }
4642
4643    #[test]
4644    fn test_parse_cfi_instruction_restore() {
4645        let expected_rest = [1, 2, 3, 4];
4646        let expected_reg = 3;
4647        let section = Section::with_endian(Endian::Little)
4648            .D8(constants::DW_CFA_restore.0 | expected_reg)
4649            .append_bytes(&expected_rest);
4650        let contents = section.get_contents().unwrap();
4651        let input = &mut EndianSlice::new(&contents, LittleEndian);
4652        assert_eq!(
4653            parse_cfi_instruction(input, 8),
4654            Ok(CallFrameInstruction::Restore {
4655                register: Register(expected_reg.into()),
4656            })
4657        );
4658        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4659    }
4660
4661    #[test]
4662    fn test_parse_cfi_instruction_nop() {
4663        let expected_rest = [1, 2, 3, 4];
4664        let section = Section::with_endian(Endian::Little)
4665            .D8(constants::DW_CFA_nop.0)
4666            .append_bytes(&expected_rest);
4667        let contents = section.get_contents().unwrap();
4668        let input = &mut EndianSlice::new(&contents, LittleEndian);
4669        assert_eq!(
4670            parse_cfi_instruction(input, 8),
4671            Ok(CallFrameInstruction::Nop)
4672        );
4673        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4674    }
4675
4676    #[test]
4677    fn test_parse_cfi_instruction_set_loc() {
4678        let expected_rest = [1, 2, 3, 4];
4679        let expected_addr = 0xdead_beef;
4680        let section = Section::with_endian(Endian::Little)
4681            .D8(constants::DW_CFA_set_loc.0)
4682            .L64(expected_addr)
4683            .append_bytes(&expected_rest);
4684        let contents = section.get_contents().unwrap();
4685        let input = &mut EndianSlice::new(&contents, LittleEndian);
4686        assert_eq!(
4687            parse_cfi_instruction(input, 8),
4688            Ok(CallFrameInstruction::SetLoc {
4689                address: expected_addr,
4690            })
4691        );
4692        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4693    }
4694
4695    #[test]
4696    fn test_parse_cfi_instruction_set_loc_encoding() {
4697        let text_base = 0xfeed_face;
4698        let addr_offset = 0xbeef;
4699        let expected_addr = text_base + addr_offset;
4700        let expected_rest = [1, 2, 3, 4];
4701        let section = Section::with_endian(Endian::Little)
4702            .D8(constants::DW_CFA_set_loc.0)
4703            .L64(addr_offset)
4704            .append_bytes(&expected_rest);
4705        let contents = section.get_contents().unwrap();
4706        let input = &mut EndianSlice::new(&contents, LittleEndian);
4707        let parameters = &PointerEncodingParameters {
4708            bases: &BaseAddresses::default().set_text(text_base).eh_frame,
4709            func_base: None,
4710            address_size: 8,
4711            section: &EndianSlice::new(&[], LittleEndian),
4712        };
4713        assert_eq!(
4714            CallFrameInstruction::parse(
4715                input,
4716                Some(constants::DW_EH_PE_textrel),
4717                parameters,
4718                Vendor::Default
4719            ),
4720            Ok(CallFrameInstruction::SetLoc {
4721                address: expected_addr,
4722            })
4723        );
4724        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4725    }
4726
4727    #[test]
4728    fn test_parse_cfi_instruction_advance_loc1() {
4729        let expected_rest = [1, 2, 3, 4];
4730        let expected_delta = 8;
4731        let section = Section::with_endian(Endian::Little)
4732            .D8(constants::DW_CFA_advance_loc1.0)
4733            .D8(expected_delta)
4734            .append_bytes(&expected_rest);
4735        let contents = section.get_contents().unwrap();
4736        let input = &mut EndianSlice::new(&contents, LittleEndian);
4737        assert_eq!(
4738            parse_cfi_instruction(input, 8),
4739            Ok(CallFrameInstruction::AdvanceLoc {
4740                delta: u32::from(expected_delta),
4741            })
4742        );
4743        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4744    }
4745
4746    #[test]
4747    fn test_parse_cfi_instruction_advance_loc2() {
4748        let expected_rest = [1, 2, 3, 4];
4749        let expected_delta = 500;
4750        let section = Section::with_endian(Endian::Little)
4751            .D8(constants::DW_CFA_advance_loc2.0)
4752            .L16(expected_delta)
4753            .append_bytes(&expected_rest);
4754        let contents = section.get_contents().unwrap();
4755        let input = &mut EndianSlice::new(&contents, LittleEndian);
4756        assert_eq!(
4757            parse_cfi_instruction(input, 8),
4758            Ok(CallFrameInstruction::AdvanceLoc {
4759                delta: u32::from(expected_delta),
4760            })
4761        );
4762        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4763    }
4764
4765    #[test]
4766    fn test_parse_cfi_instruction_advance_loc4() {
4767        let expected_rest = [1, 2, 3, 4];
4768        let expected_delta = 1 << 20;
4769        let section = Section::with_endian(Endian::Little)
4770            .D8(constants::DW_CFA_advance_loc4.0)
4771            .L32(expected_delta)
4772            .append_bytes(&expected_rest);
4773        let contents = section.get_contents().unwrap();
4774        let input = &mut EndianSlice::new(&contents, LittleEndian);
4775        assert_eq!(
4776            parse_cfi_instruction(input, 8),
4777            Ok(CallFrameInstruction::AdvanceLoc {
4778                delta: expected_delta,
4779            })
4780        );
4781        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4782    }
4783
4784    #[test]
4785    fn test_parse_cfi_instruction_offset_extended() {
4786        let expected_rest = [1, 2, 3, 4];
4787        let expected_reg = 7;
4788        let expected_offset = 33;
4789        let section = Section::with_endian(Endian::Little)
4790            .D8(constants::DW_CFA_offset_extended.0)
4791            .uleb(expected_reg.into())
4792            .uleb(expected_offset)
4793            .append_bytes(&expected_rest);
4794        let contents = section.get_contents().unwrap();
4795        let input = &mut EndianSlice::new(&contents, LittleEndian);
4796        assert_eq!(
4797            parse_cfi_instruction(input, 8),
4798            Ok(CallFrameInstruction::Offset {
4799                register: Register(expected_reg),
4800                factored_offset: expected_offset,
4801            })
4802        );
4803        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4804    }
4805
4806    #[test]
4807    fn test_parse_cfi_instruction_restore_extended() {
4808        let expected_rest = [1, 2, 3, 4];
4809        let expected_reg = 7;
4810        let section = Section::with_endian(Endian::Little)
4811            .D8(constants::DW_CFA_restore_extended.0)
4812            .uleb(expected_reg.into())
4813            .append_bytes(&expected_rest);
4814        let contents = section.get_contents().unwrap();
4815        let input = &mut EndianSlice::new(&contents, LittleEndian);
4816        assert_eq!(
4817            parse_cfi_instruction(input, 8),
4818            Ok(CallFrameInstruction::Restore {
4819                register: Register(expected_reg),
4820            })
4821        );
4822        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4823    }
4824
4825    #[test]
4826    fn test_parse_cfi_instruction_undefined() {
4827        let expected_rest = [1, 2, 3, 4];
4828        let expected_reg = 7;
4829        let section = Section::with_endian(Endian::Little)
4830            .D8(constants::DW_CFA_undefined.0)
4831            .uleb(expected_reg.into())
4832            .append_bytes(&expected_rest);
4833        let contents = section.get_contents().unwrap();
4834        let input = &mut EndianSlice::new(&contents, LittleEndian);
4835        assert_eq!(
4836            parse_cfi_instruction(input, 8),
4837            Ok(CallFrameInstruction::Undefined {
4838                register: Register(expected_reg),
4839            })
4840        );
4841        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4842    }
4843
4844    #[test]
4845    fn test_parse_cfi_instruction_same_value() {
4846        let expected_rest = [1, 2, 3, 4];
4847        let expected_reg = 7;
4848        let section = Section::with_endian(Endian::Little)
4849            .D8(constants::DW_CFA_same_value.0)
4850            .uleb(expected_reg.into())
4851            .append_bytes(&expected_rest);
4852        let contents = section.get_contents().unwrap();
4853        let input = &mut EndianSlice::new(&contents, LittleEndian);
4854        assert_eq!(
4855            parse_cfi_instruction(input, 8),
4856            Ok(CallFrameInstruction::SameValue {
4857                register: Register(expected_reg),
4858            })
4859        );
4860        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4861    }
4862
4863    #[test]
4864    fn test_parse_cfi_instruction_register() {
4865        let expected_rest = [1, 2, 3, 4];
4866        let expected_dest_reg = 7;
4867        let expected_src_reg = 8;
4868        let section = Section::with_endian(Endian::Little)
4869            .D8(constants::DW_CFA_register.0)
4870            .uleb(expected_dest_reg.into())
4871            .uleb(expected_src_reg.into())
4872            .append_bytes(&expected_rest);
4873        let contents = section.get_contents().unwrap();
4874        let input = &mut EndianSlice::new(&contents, LittleEndian);
4875        assert_eq!(
4876            parse_cfi_instruction(input, 8),
4877            Ok(CallFrameInstruction::Register {
4878                dest_register: Register(expected_dest_reg),
4879                src_register: Register(expected_src_reg),
4880            })
4881        );
4882        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4883    }
4884
4885    #[test]
4886    fn test_parse_cfi_instruction_remember_state() {
4887        let expected_rest = [1, 2, 3, 4];
4888        let section = Section::with_endian(Endian::Little)
4889            .D8(constants::DW_CFA_remember_state.0)
4890            .append_bytes(&expected_rest);
4891        let contents = section.get_contents().unwrap();
4892        let input = &mut EndianSlice::new(&contents, LittleEndian);
4893        assert_eq!(
4894            parse_cfi_instruction(input, 8),
4895            Ok(CallFrameInstruction::RememberState)
4896        );
4897        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4898    }
4899
4900    #[test]
4901    fn test_parse_cfi_instruction_restore_state() {
4902        let expected_rest = [1, 2, 3, 4];
4903        let section = Section::with_endian(Endian::Little)
4904            .D8(constants::DW_CFA_restore_state.0)
4905            .append_bytes(&expected_rest);
4906        let contents = section.get_contents().unwrap();
4907        let input = &mut EndianSlice::new(&contents, LittleEndian);
4908        assert_eq!(
4909            parse_cfi_instruction(input, 8),
4910            Ok(CallFrameInstruction::RestoreState)
4911        );
4912        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4913    }
4914
4915    #[test]
4916    fn test_parse_cfi_instruction_def_cfa() {
4917        let expected_rest = [1, 2, 3, 4];
4918        let expected_reg = 2;
4919        let expected_offset = 0;
4920        let section = Section::with_endian(Endian::Little)
4921            .D8(constants::DW_CFA_def_cfa.0)
4922            .uleb(expected_reg.into())
4923            .uleb(expected_offset)
4924            .append_bytes(&expected_rest);
4925        let contents = section.get_contents().unwrap();
4926        let input = &mut EndianSlice::new(&contents, LittleEndian);
4927        assert_eq!(
4928            parse_cfi_instruction(input, 8),
4929            Ok(CallFrameInstruction::DefCfa {
4930                register: Register(expected_reg),
4931                offset: expected_offset,
4932            })
4933        );
4934        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4935    }
4936
4937    #[test]
4938    fn test_parse_cfi_instruction_def_cfa_register() {
4939        let expected_rest = [1, 2, 3, 4];
4940        let expected_reg = 2;
4941        let section = Section::with_endian(Endian::Little)
4942            .D8(constants::DW_CFA_def_cfa_register.0)
4943            .uleb(expected_reg.into())
4944            .append_bytes(&expected_rest);
4945        let contents = section.get_contents().unwrap();
4946        let input = &mut EndianSlice::new(&contents, LittleEndian);
4947        assert_eq!(
4948            parse_cfi_instruction(input, 8),
4949            Ok(CallFrameInstruction::DefCfaRegister {
4950                register: Register(expected_reg),
4951            })
4952        );
4953        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4954    }
4955
4956    #[test]
4957    fn test_parse_cfi_instruction_def_cfa_offset() {
4958        let expected_rest = [1, 2, 3, 4];
4959        let expected_offset = 23;
4960        let section = Section::with_endian(Endian::Little)
4961            .D8(constants::DW_CFA_def_cfa_offset.0)
4962            .uleb(expected_offset)
4963            .append_bytes(&expected_rest);
4964        let contents = section.get_contents().unwrap();
4965        let input = &mut EndianSlice::new(&contents, LittleEndian);
4966        assert_eq!(
4967            parse_cfi_instruction(input, 8),
4968            Ok(CallFrameInstruction::DefCfaOffset {
4969                offset: expected_offset,
4970            })
4971        );
4972        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4973    }
4974
4975    #[test]
4976    fn test_parse_cfi_instruction_def_cfa_expression() {
4977        let expected_rest = [1, 2, 3, 4];
4978        let expected_expr = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
4979
4980        let length = Label::new();
4981        let start = Label::new();
4982        let end = Label::new();
4983
4984        let section = Section::with_endian(Endian::Little)
4985            .D8(constants::DW_CFA_def_cfa_expression.0)
4986            .D8(&length)
4987            .mark(&start)
4988            .append_bytes(&expected_expr)
4989            .mark(&end)
4990            .append_bytes(&expected_rest);
4991
4992        length.set_const((&end - &start) as u64);
4993        let expected_expression = UnwindExpression {
4994            offset: (&start - §ion.start()) as usize,
4995            length: (&end - &start) as usize,
4996        };
4997        let contents = section.get_contents().unwrap();
4998        let input = &mut EndianSlice::new(&contents, LittleEndian);
4999
5000        assert_eq!(
5001            parse_cfi_instruction(input, 8),
5002            Ok(CallFrameInstruction::DefCfaExpression {
5003                expression: expected_expression,
5004            })
5005        );
5006        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
5007    }
5008
5009    #[test]
5010    fn test_parse_cfi_instruction_expression() {
5011        let expected_rest = [1, 2, 3, 4];
5012        let expected_reg = 99;
5013        let expected_expr = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
5014
5015        let length = Label::new();
5016        let start = Label::new();
5017        let end = Label::new();
5018
5019        let section = Section::with_endian(Endian::Little)
5020            .D8(constants::DW_CFA_expression.0)
5021            .uleb(expected_reg.into())
5022            .D8(&length)
5023            .mark(&start)
5024            .append_bytes(&expected_expr)
5025            .mark(&end)
5026            .append_bytes(&expected_rest);
5027
5028        length.set_const((&end - &start) as u64);
5029        let expected_expression = UnwindExpression {
5030            offset: (&start - §ion.start()) as usize,
5031            length: (&end - &start) as usize,
5032        };
5033        let contents = section.get_contents().unwrap();
5034        let input = &mut EndianSlice::new(&contents, LittleEndian);
5035
5036        assert_eq!(
5037            parse_cfi_instruction(input, 8),
5038            Ok(CallFrameInstruction::Expression {
5039                register: Register(expected_reg),
5040                expression: expected_expression,
5041            })
5042        );
5043        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
5044    }
5045
5046    #[test]
5047    fn test_parse_cfi_instruction_offset_extended_sf() {
5048        let expected_rest = [1, 2, 3, 4];
5049        let expected_reg = 7;
5050        let expected_offset = -33;
5051        let section = Section::with_endian(Endian::Little)
5052            .D8(constants::DW_CFA_offset_extended_sf.0)
5053            .uleb(expected_reg.into())
5054            .sleb(expected_offset)
5055            .append_bytes(&expected_rest);
5056        let contents = section.get_contents().unwrap();
5057        let input = &mut EndianSlice::new(&contents, LittleEndian);
5058        assert_eq!(
5059            parse_cfi_instruction(input, 8),
5060            Ok(CallFrameInstruction::OffsetExtendedSf {
5061                register: Register(expected_reg),
5062                factored_offset: expected_offset,
5063            })
5064        );
5065        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
5066    }
5067
5068    #[test]
5069    fn test_parse_cfi_instruction_def_cfa_sf() {
5070        let expected_rest = [1, 2, 3, 4];
5071        let expected_reg = 2;
5072        let expected_offset = -9999;
5073        let section = Section::with_endian(Endian::Little)
5074            .D8(constants::DW_CFA_def_cfa_sf.0)
5075            .uleb(expected_reg.into())
5076            .sleb(expected_offset)
5077            .append_bytes(&expected_rest);
5078        let contents = section.get_contents().unwrap();
5079        let input = &mut EndianSlice::new(&contents, LittleEndian);
5080        assert_eq!(
5081            parse_cfi_instruction(input, 8),
5082            Ok(CallFrameInstruction::DefCfaSf {
5083                register: Register(expected_reg),
5084                factored_offset: expected_offset,
5085            })
5086        );
5087        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
5088    }
5089
5090    #[test]
5091    fn test_parse_cfi_instruction_def_cfa_offset_sf() {
5092        let expected_rest = [1, 2, 3, 4];
5093        let expected_offset = -123;
5094        let section = Section::with_endian(Endian::Little)
5095            .D8(constants::DW_CFA_def_cfa_offset_sf.0)
5096            .sleb(expected_offset)
5097            .append_bytes(&expected_rest);
5098        let contents = section.get_contents().unwrap();
5099        let input = &mut EndianSlice::new(&contents, LittleEndian);
5100        assert_eq!(
5101            parse_cfi_instruction(input, 8),
5102            Ok(CallFrameInstruction::DefCfaOffsetSf {
5103                factored_offset: expected_offset,
5104            })
5105        );
5106        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
5107    }
5108
5109    #[test]
5110    fn test_parse_cfi_instruction_val_offset() {
5111        let expected_rest = [1, 2, 3, 4];
5112        let expected_reg = 50;
5113        let expected_offset = 23;
5114        let section = Section::with_endian(Endian::Little)
5115            .D8(constants::DW_CFA_val_offset.0)
5116            .uleb(expected_reg.into())
5117            .uleb(expected_offset)
5118            .append_bytes(&expected_rest);
5119        let contents = section.get_contents().unwrap();
5120        let input = &mut EndianSlice::new(&contents, LittleEndian);
5121        assert_eq!(
5122            parse_cfi_instruction(input, 8),
5123            Ok(CallFrameInstruction::ValOffset {
5124                register: Register(expected_reg),
5125                factored_offset: expected_offset,
5126            })
5127        );
5128        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
5129    }
5130
5131    #[test]
5132    fn test_parse_cfi_instruction_val_offset_sf() {
5133        let expected_rest = [1, 2, 3, 4];
5134        let expected_reg = 50;
5135        let expected_offset = -23;
5136        let section = Section::with_endian(Endian::Little)
5137            .D8(constants::DW_CFA_val_offset_sf.0)
5138            .uleb(expected_reg.into())
5139            .sleb(expected_offset)
5140            .append_bytes(&expected_rest);
5141        let contents = section.get_contents().unwrap();
5142        let input = &mut EndianSlice::new(&contents, LittleEndian);
5143        assert_eq!(
5144            parse_cfi_instruction(input, 8),
5145            Ok(CallFrameInstruction::ValOffsetSf {
5146                register: Register(expected_reg),
5147                factored_offset: expected_offset,
5148            })
5149        );
5150        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
5151    }
5152
5153    #[test]
5154    fn test_parse_cfi_instruction_val_expression() {
5155        let expected_rest = [1, 2, 3, 4];
5156        let expected_reg = 50;
5157        let expected_expr = [2, 2, 1, 1, 5, 5];
5158
5159        let length = Label::new();
5160        let start = Label::new();
5161        let end = Label::new();
5162
5163        let section = Section::with_endian(Endian::Little)
5164            .D8(constants::DW_CFA_val_expression.0)
5165            .uleb(expected_reg.into())
5166            .D8(&length)
5167            .mark(&start)
5168            .append_bytes(&expected_expr)
5169            .mark(&end)
5170            .append_bytes(&expected_rest);
5171
5172        length.set_const((&end - &start) as u64);
5173        let expected_expression = UnwindExpression {
5174            offset: (&start - §ion.start()) as usize,
5175            length: (&end - &start) as usize,
5176        };
5177        let contents = section.get_contents().unwrap();
5178        let input = &mut EndianSlice::new(&contents, LittleEndian);
5179
5180        assert_eq!(
5181            parse_cfi_instruction(input, 8),
5182            Ok(CallFrameInstruction::ValExpression {
5183                register: Register(expected_reg),
5184                expression: expected_expression,
5185            })
5186        );
5187        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
5188    }
5189
5190    #[test]
5191    fn test_parse_cfi_instruction_negate_ra_state() {
5192        let expected_rest = [1, 2, 3, 4];
5193        let section = Section::with_endian(Endian::Little)
5194            .D8(constants::DW_CFA_AARCH64_negate_ra_state.0)
5195            .append_bytes(&expected_rest);
5196        let contents = section.get_contents().unwrap();
5197        let input = &mut EndianSlice::new(&contents, LittleEndian);
5198        let parameters = &PointerEncodingParameters {
5199            bases: &SectionBaseAddresses::default(),
5200            func_base: None,
5201            address_size: 8,
5202            section: &EndianSlice::default(),
5203        };
5204        assert_eq!(
5205            CallFrameInstruction::parse(input, None, parameters, Vendor::AArch64),
5206            Ok(CallFrameInstruction::NegateRaState)
5207        );
5208        assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
5209    }
5210
5211    #[test]
5212    fn test_parse_cfi_instruction_unknown_instruction() {
5213        let expected_rest = [1, 2, 3, 4];
5214        let unknown_instr = constants::DwCfa(0b0011_1111);
5215        let section = Section::with_endian(Endian::Little)
5216            .D8(unknown_instr.0)
5217            .append_bytes(&expected_rest);
5218        let contents = section.get_contents().unwrap();
5219        let input = &mut EndianSlice::new(&contents, LittleEndian);
5220        assert_eq!(
5221            parse_cfi_instruction(input, 8),
5222            Err(Error::UnknownCallFrameInstruction(unknown_instr))
5223        );
5224    }
5225
5226    #[test]
5227    fn test_call_frame_instruction_iter_ok() {
5228        let expected_reg = 50;
5229        let expected_expr = [2, 2, 1, 1, 5, 5];
5230        let expected_delta = 230;
5231
5232        let length = Label::new();
5233        let start = Label::new();
5234        let end = Label::new();
5235
5236        let section = Section::with_endian(Endian::Big)
5237            .D8(constants::DW_CFA_val_expression.0)
5238            .uleb(expected_reg.into())
5239            .D8(&length)
5240            .mark(&start)
5241            .append_bytes(&expected_expr)
5242            .mark(&end)
5243            .D8(constants::DW_CFA_advance_loc1.0)
5244            .D8(expected_delta);
5245
5246        length.set_const((&end - &start) as u64);
5247        let expected_expression = UnwindExpression {
5248            offset: (&start - §ion.start()) as usize,
5249            length: (&end - &start) as usize,
5250        };
5251        let contents = section.get_contents().unwrap();
5252        let input = EndianSlice::new(&contents, BigEndian);
5253        let parameters = PointerEncodingParameters {
5254            bases: &SectionBaseAddresses::default(),
5255            func_base: None,
5256            address_size: 8,
5257            section: &input,
5258        };
5259        let mut iter = CallFrameInstructionIter {
5260            input,
5261            address_encoding: None,
5262            parameters,
5263            vendor: Vendor::Default,
5264        };
5265
5266        assert_eq!(
5267            iter.next(),
5268            Ok(Some(CallFrameInstruction::ValExpression {
5269                register: Register(expected_reg),
5270                expression: expected_expression,
5271            }))
5272        );
5273
5274        assert_eq!(
5275            iter.next(),
5276            Ok(Some(CallFrameInstruction::AdvanceLoc {
5277                delta: u32::from(expected_delta),
5278            }))
5279        );
5280
5281        assert_eq!(iter.next(), Ok(None));
5282    }
5283
5284    #[test]
5285    fn test_call_frame_instruction_iter_err() {
5286        let section = Section::with_endian(Endian::Big).D8(constants::DW_CFA_advance_loc1.0);
5288
5289        let contents = section.get_contents().unwrap();
5290        let input = EndianSlice::new(&contents, BigEndian);
5291        let parameters = PointerEncodingParameters {
5292            bases: &SectionBaseAddresses::default(),
5293            func_base: None,
5294            address_size: 8,
5295            section: &EndianSlice::default(),
5296        };
5297        let mut iter = CallFrameInstructionIter {
5298            input,
5299            address_encoding: None,
5300            parameters,
5301            vendor: Vendor::Default,
5302        };
5303
5304        assert_eq!(
5305            iter.next().map_eof(&contents),
5306            Err(Error::UnexpectedEof(ReaderOffsetId(1)))
5307        );
5308        assert_eq!(iter.next(), Ok(None));
5309    }
5310
5311    fn assert_eval<'a, I>(
5312        mut initial_ctx: UnwindContext<usize>,
5313        expected_ctx: UnwindContext<usize>,
5314        cie: CommonInformationEntry<EndianSlice<'a, LittleEndian>>,
5315        fde: Option<FrameDescriptionEntry<EndianSlice<'a, LittleEndian>>>,
5316        instructions: I,
5317    ) where
5318        I: AsRef<[(Result<bool>, CallFrameInstruction<usize>)]>,
5319    {
5320        {
5321            let section = &DebugFrame::from(EndianSlice::default());
5322            let bases = &BaseAddresses::default();
5323            let mut table = match fde {
5324                Some(fde) => UnwindTable::new_for_fde(section, bases, &mut initial_ctx, &fde),
5325                None => UnwindTable::new_for_cie(section, bases, &mut initial_ctx, &cie),
5326            };
5327            for (expected_result, instruction) in instructions.as_ref() {
5328                assert_eq!(*expected_result, table.evaluate(instruction.clone()));
5329            }
5330        }
5331
5332        assert_eq!(expected_ctx, initial_ctx);
5333    }
5334
5335    fn make_test_cie<'a>() -> CommonInformationEntry<EndianSlice<'a, LittleEndian>> {
5336        CommonInformationEntry {
5337            offset: 0,
5338            format: Format::Dwarf64,
5339            length: 0,
5340            return_address_register: Register(0),
5341            version: 4,
5342            address_size: mem::size_of::<usize>() as u8,
5343            initial_instructions: EndianSlice::new(&[], LittleEndian),
5344            augmentation: None,
5345            data_alignment_factor: 2,
5346            code_alignment_factor: 3,
5347        }
5348    }
5349
5350    #[test]
5351    fn test_eval_set_loc() {
5352        let cie = make_test_cie();
5353        let ctx = UnwindContext::new();
5354        let mut expected = ctx.clone();
5355        expected.row_mut().end_address = 42;
5356        let instructions = [(Ok(true), CallFrameInstruction::SetLoc { address: 42 })];
5357        assert_eval(ctx, expected, cie, None, instructions);
5358    }
5359
5360    #[test]
5361    fn test_eval_set_loc_backwards() {
5362        let cie = make_test_cie();
5363        let mut ctx = UnwindContext::new();
5364        ctx.row_mut().start_address = 999;
5365        let expected = ctx.clone();
5366        let instructions = [(
5367            Err(Error::InvalidAddressRange),
5368            CallFrameInstruction::SetLoc { address: 42 },
5369        )];
5370        assert_eval(ctx, expected, cie, None, instructions);
5371    }
5372
5373    #[test]
5374    fn test_eval_advance_loc() {
5375        let cie = make_test_cie();
5376        let mut ctx = UnwindContext::new();
5377        ctx.row_mut().start_address = 3;
5378        let mut expected = ctx.clone();
5379        expected.row_mut().end_address = 3 + 2 * cie.code_alignment_factor;
5380        let instructions = [(Ok(true), CallFrameInstruction::AdvanceLoc { delta: 2 })];
5381        assert_eval(ctx, expected, cie, None, instructions);
5382    }
5383
5384    #[test]
5385    fn test_eval_advance_loc_overflow_32() {
5386        let mut cie = make_test_cie();
5387        cie.address_size = 4;
5388        let mut ctx = UnwindContext::new();
5389        ctx.row_mut().start_address = u32::MAX.into();
5390        let expected = ctx.clone();
5391        let instructions = [(
5392            Err(Error::AddressOverflow),
5393            CallFrameInstruction::AdvanceLoc { delta: 42 },
5394        )];
5395        assert_eval(ctx, expected, cie, None, instructions);
5396    }
5397
5398    #[test]
5399    fn test_eval_advance_loc_overflow_64() {
5400        let mut cie = make_test_cie();
5401        cie.address_size = 8;
5402        let mut ctx = UnwindContext::new();
5403        ctx.row_mut().start_address = u64::MAX;
5404        let expected = ctx.clone();
5405        let instructions = [(
5406            Err(Error::AddressOverflow),
5407            CallFrameInstruction::AdvanceLoc { delta: 42 },
5408        )];
5409        assert_eval(ctx, expected, cie, None, instructions);
5410    }
5411
5412    #[test]
5413    fn test_eval_def_cfa() {
5414        let cie = make_test_cie();
5415        let ctx = UnwindContext::new();
5416        let mut expected = ctx.clone();
5417        expected.set_cfa(CfaRule::RegisterAndOffset {
5418            register: Register(42),
5419            offset: 36,
5420        });
5421        let instructions = [(
5422            Ok(false),
5423            CallFrameInstruction::DefCfa {
5424                register: Register(42),
5425                offset: 36,
5426            },
5427        )];
5428        assert_eval(ctx, expected, cie, None, instructions);
5429    }
5430
5431    #[test]
5432    fn test_eval_def_cfa_sf() {
5433        let cie = make_test_cie();
5434        let ctx = UnwindContext::new();
5435        let mut expected = ctx.clone();
5436        expected.set_cfa(CfaRule::RegisterAndOffset {
5437            register: Register(42),
5438            offset: 36 * cie.data_alignment_factor as i64,
5439        });
5440        let instructions = [(
5441            Ok(false),
5442            CallFrameInstruction::DefCfaSf {
5443                register: Register(42),
5444                factored_offset: 36,
5445            },
5446        )];
5447        assert_eval(ctx, expected, cie, None, instructions);
5448    }
5449
5450    #[test]
5451    fn test_eval_def_cfa_register() {
5452        let cie = make_test_cie();
5453        let mut ctx = UnwindContext::new();
5454        ctx.set_cfa(CfaRule::RegisterAndOffset {
5455            register: Register(3),
5456            offset: 8,
5457        });
5458        let mut expected = ctx.clone();
5459        expected.set_cfa(CfaRule::RegisterAndOffset {
5460            register: Register(42),
5461            offset: 8,
5462        });
5463        let instructions = [(
5464            Ok(false),
5465            CallFrameInstruction::DefCfaRegister {
5466                register: Register(42),
5467            },
5468        )];
5469        assert_eval(ctx, expected, cie, None, instructions);
5470    }
5471
5472    #[test]
5473    fn test_eval_def_cfa_register_invalid_context() {
5474        let cie = make_test_cie();
5475        let mut ctx = UnwindContext::new();
5476        ctx.set_cfa(CfaRule::Expression(UnwindExpression {
5477            offset: 0,
5478            length: 0,
5479        }));
5480        let expected = ctx.clone();
5481        let instructions = [(
5482            Err(Error::CfiInstructionInInvalidContext),
5483            CallFrameInstruction::DefCfaRegister {
5484                register: Register(42),
5485            },
5486        )];
5487        assert_eval(ctx, expected, cie, None, instructions);
5488    }
5489
5490    #[test]
5491    fn test_eval_def_cfa_offset() {
5492        let cie = make_test_cie();
5493        let mut ctx = UnwindContext::new();
5494        ctx.set_cfa(CfaRule::RegisterAndOffset {
5495            register: Register(3),
5496            offset: 8,
5497        });
5498        let mut expected = ctx.clone();
5499        expected.set_cfa(CfaRule::RegisterAndOffset {
5500            register: Register(3),
5501            offset: 42,
5502        });
5503        let instructions = [(Ok(false), CallFrameInstruction::DefCfaOffset { offset: 42 })];
5504        assert_eval(ctx, expected, cie, None, instructions);
5505    }
5506
5507    #[test]
5508    fn test_eval_def_cfa_offset_invalid_context() {
5509        let cie = make_test_cie();
5510        let mut ctx = UnwindContext::new();
5511        ctx.set_cfa(CfaRule::Expression(UnwindExpression {
5512            offset: 10,
5513            length: 11,
5514        }));
5515        let expected = ctx.clone();
5516        let instructions = [(
5517            Err(Error::CfiInstructionInInvalidContext),
5518            CallFrameInstruction::DefCfaOffset { offset: 1993 },
5519        )];
5520        assert_eval(ctx, expected, cie, None, instructions);
5521    }
5522
5523    #[test]
5524    fn test_eval_def_cfa_expression() {
5525        let expr = UnwindExpression {
5526            offset: 10,
5527            length: 11,
5528        };
5529        let cie = make_test_cie();
5530        let ctx = UnwindContext::new();
5531        let mut expected = ctx.clone();
5532        expected.set_cfa(CfaRule::Expression(expr));
5533        let instructions = [(
5534            Ok(false),
5535            CallFrameInstruction::DefCfaExpression { expression: expr },
5536        )];
5537        assert_eval(ctx, expected, cie, None, instructions);
5538    }
5539
5540    #[test]
5541    fn test_eval_undefined() {
5542        let cie = make_test_cie();
5543        let ctx = UnwindContext::new();
5544        let mut expected = ctx.clone();
5545        expected
5546            .set_register_rule(Register(5), RegisterRule::Undefined)
5547            .unwrap();
5548        let instructions = [(
5549            Ok(false),
5550            CallFrameInstruction::Undefined {
5551                register: Register(5),
5552            },
5553        )];
5554        assert_eval(ctx, expected, cie, None, instructions);
5555    }
5556
5557    #[test]
5558    fn test_eval_same_value() {
5559        let cie = make_test_cie();
5560        let ctx = UnwindContext::new();
5561        let mut expected = ctx.clone();
5562        expected
5563            .set_register_rule(Register(0), RegisterRule::SameValue)
5564            .unwrap();
5565        let instructions = [(
5566            Ok(false),
5567            CallFrameInstruction::SameValue {
5568                register: Register(0),
5569            },
5570        )];
5571        assert_eval(ctx, expected, cie, None, instructions);
5572    }
5573
5574    #[test]
5575    fn test_eval_offset() {
5576        let cie = make_test_cie();
5577        let ctx = UnwindContext::new();
5578        let mut expected = ctx.clone();
5579        expected
5580            .set_register_rule(
5581                Register(2),
5582                RegisterRule::Offset(3 * cie.data_alignment_factor),
5583            )
5584            .unwrap();
5585        let instructions = [(
5586            Ok(false),
5587            CallFrameInstruction::Offset {
5588                register: Register(2),
5589                factored_offset: 3,
5590            },
5591        )];
5592        assert_eval(ctx, expected, cie, None, instructions);
5593    }
5594
5595    #[test]
5596    fn test_eval_offset_extended_sf() {
5597        let cie = make_test_cie();
5598        let ctx = UnwindContext::new();
5599        let mut expected = ctx.clone();
5600        expected
5601            .set_register_rule(
5602                Register(4),
5603                RegisterRule::Offset(-3 * cie.data_alignment_factor),
5604            )
5605            .unwrap();
5606        let instructions = [(
5607            Ok(false),
5608            CallFrameInstruction::OffsetExtendedSf {
5609                register: Register(4),
5610                factored_offset: -3,
5611            },
5612        )];
5613        assert_eval(ctx, expected, cie, None, instructions);
5614    }
5615
5616    #[test]
5617    fn test_eval_val_offset() {
5618        let cie = make_test_cie();
5619        let ctx = UnwindContext::new();
5620        let mut expected = ctx.clone();
5621        expected
5622            .set_register_rule(
5623                Register(5),
5624                RegisterRule::ValOffset(7 * cie.data_alignment_factor),
5625            )
5626            .unwrap();
5627        let instructions = [(
5628            Ok(false),
5629            CallFrameInstruction::ValOffset {
5630                register: Register(5),
5631                factored_offset: 7,
5632            },
5633        )];
5634        assert_eval(ctx, expected, cie, None, instructions);
5635    }
5636
5637    #[test]
5638    fn test_eval_val_offset_sf() {
5639        let cie = make_test_cie();
5640        let ctx = UnwindContext::new();
5641        let mut expected = ctx.clone();
5642        expected
5643            .set_register_rule(
5644                Register(5),
5645                RegisterRule::ValOffset(-7 * cie.data_alignment_factor),
5646            )
5647            .unwrap();
5648        let instructions = [(
5649            Ok(false),
5650            CallFrameInstruction::ValOffsetSf {
5651                register: Register(5),
5652                factored_offset: -7,
5653            },
5654        )];
5655        assert_eval(ctx, expected, cie, None, instructions);
5656    }
5657
5658    #[test]
5659    fn test_eval_expression() {
5660        let expr = UnwindExpression {
5661            offset: 10,
5662            length: 11,
5663        };
5664        let cie = make_test_cie();
5665        let ctx = UnwindContext::new();
5666        let mut expected = ctx.clone();
5667        expected
5668            .set_register_rule(Register(9), RegisterRule::Expression(expr))
5669            .unwrap();
5670        let instructions = [(
5671            Ok(false),
5672            CallFrameInstruction::Expression {
5673                register: Register(9),
5674                expression: expr,
5675            },
5676        )];
5677        assert_eval(ctx, expected, cie, None, instructions);
5678    }
5679
5680    #[test]
5681    fn test_eval_val_expression() {
5682        let expr = UnwindExpression {
5683            offset: 10,
5684            length: 11,
5685        };
5686        let cie = make_test_cie();
5687        let ctx = UnwindContext::new();
5688        let mut expected = ctx.clone();
5689        expected
5690            .set_register_rule(Register(9), RegisterRule::ValExpression(expr))
5691            .unwrap();
5692        let instructions = [(
5693            Ok(false),
5694            CallFrameInstruction::ValExpression {
5695                register: Register(9),
5696                expression: expr,
5697            },
5698        )];
5699        assert_eval(ctx, expected, cie, None, instructions);
5700    }
5701
5702    #[test]
5703    fn test_eval_restore() {
5704        let cie = make_test_cie();
5705        let fde = FrameDescriptionEntry {
5706            offset: 0,
5707            format: Format::Dwarf64,
5708            length: 0,
5709            address_range: 0,
5710            augmentation: None,
5711            initial_address: 0,
5712            cie: cie.clone(),
5713            instructions: EndianSlice::new(&[], LittleEndian),
5714        };
5715
5716        let mut ctx = UnwindContext::new();
5717        ctx.set_register_rule(Register(0), RegisterRule::Offset(1))
5718            .unwrap();
5719        ctx.save_initial_rules().unwrap();
5720        let expected = ctx.clone();
5721        ctx.set_register_rule(Register(0), RegisterRule::Offset(2))
5722            .unwrap();
5723
5724        let instructions = [(
5725            Ok(false),
5726            CallFrameInstruction::Restore {
5727                register: Register(0),
5728            },
5729        )];
5730        assert_eval(ctx, expected, cie, Some(fde), instructions);
5731    }
5732
5733    #[test]
5734    fn test_eval_restore_havent_saved_initial_context() {
5735        let cie = make_test_cie();
5736        let ctx = UnwindContext::new();
5737        let expected = ctx.clone();
5738        let instructions = [(
5739            Err(Error::CfiInstructionInInvalidContext),
5740            CallFrameInstruction::Restore {
5741                register: Register(0),
5742            },
5743        )];
5744        assert_eval(ctx, expected, cie, None, instructions);
5745    }
5746
5747    #[test]
5748    fn test_eval_remember_state() {
5749        let cie = make_test_cie();
5750        let ctx = UnwindContext::new();
5751        let mut expected = ctx.clone();
5752        expected.push_row().unwrap();
5753        let instructions = [(Ok(false), CallFrameInstruction::RememberState)];
5754        assert_eval(ctx, expected, cie, None, instructions);
5755    }
5756
5757    #[test]
5758    fn test_eval_restore_state() {
5759        let cie = make_test_cie();
5760
5761        let mut ctx = UnwindContext::new();
5762        ctx.set_start_address(1);
5763        ctx.set_register_rule(Register(0), RegisterRule::SameValue)
5764            .unwrap();
5765        let mut expected = ctx.clone();
5766        ctx.push_row().unwrap();
5767        ctx.set_start_address(2);
5768        ctx.set_register_rule(Register(0), RegisterRule::Offset(16))
5769            .unwrap();
5770
5771        expected.set_start_address(2);
5773
5774        let instructions = [
5775            (Ok(false), CallFrameInstruction::RestoreState),
5777            (
5779                Err(Error::PopWithEmptyStack),
5780                CallFrameInstruction::RestoreState,
5781            ),
5782        ];
5783
5784        assert_eval(ctx, expected, cie, None, instructions);
5785    }
5786
5787    #[test]
5788    fn test_eval_negate_ra_state() {
5789        let cie = make_test_cie();
5790        let ctx = UnwindContext::new();
5791        let mut expected = ctx.clone();
5792        expected
5793            .set_register_rule(crate::AArch64::RA_SIGN_STATE, RegisterRule::Constant(1))
5794            .unwrap();
5795        let instructions = [(Ok(false), CallFrameInstruction::NegateRaState)];
5796        assert_eval(ctx, expected, cie, None, instructions);
5797
5798        let cie = make_test_cie();
5799        let ctx = UnwindContext::new();
5800        let mut expected = ctx.clone();
5801        expected
5802            .set_register_rule(crate::AArch64::RA_SIGN_STATE, RegisterRule::Constant(0))
5803            .unwrap();
5804        let instructions = [
5805            (Ok(false), CallFrameInstruction::NegateRaState),
5806            (Ok(false), CallFrameInstruction::NegateRaState),
5807        ];
5808        assert_eval(ctx, expected, cie, None, instructions);
5809
5810        let cie = make_test_cie();
5812        let ctx = UnwindContext::new();
5813        let mut expected = ctx.clone();
5814        expected
5815            .set_register_rule(
5816                crate::AArch64::RA_SIGN_STATE,
5817                RegisterRule::Offset(cie.data_alignment_factor as i64),
5818            )
5819            .unwrap();
5820        let instructions = [
5821            (
5822                Ok(false),
5823                CallFrameInstruction::Offset {
5824                    register: crate::AArch64::RA_SIGN_STATE,
5825                    factored_offset: 1,
5826                },
5827            ),
5828            (
5829                Err(Error::CfiInstructionInInvalidContext),
5830                CallFrameInstruction::NegateRaState,
5831            ),
5832        ];
5833        assert_eval(ctx, expected, cie, None, instructions);
5834    }
5835
5836    #[test]
5837    fn test_eval_nop() {
5838        let cie = make_test_cie();
5839        let ctx = UnwindContext::new();
5840        let expected = ctx.clone();
5841        let instructions = [(Ok(false), CallFrameInstruction::Nop)];
5842        assert_eval(ctx, expected, cie, None, instructions);
5843    }
5844
5845    #[test]
5846    fn test_unwind_table_cie_no_rule() {
5847        let initial_instructions = Section::with_endian(Endian::Little)
5848            .D8(constants::DW_CFA_def_cfa_sf.0)
5850            .uleb(4)
5851            .sleb(-12)
5852            .append_repeated(constants::DW_CFA_nop.0, 4);
5853        let initial_instructions = initial_instructions.get_contents().unwrap();
5854
5855        let cie = CommonInformationEntry {
5856            offset: 0,
5857            length: 0,
5858            format: Format::Dwarf32,
5859            version: 4,
5860            augmentation: None,
5861            address_size: 8,
5862            code_alignment_factor: 1,
5863            data_alignment_factor: 1,
5864            return_address_register: Register(3),
5865            initial_instructions: EndianSlice::new(&initial_instructions, LittleEndian),
5866        };
5867
5868        let instructions = Section::with_endian(Endian::Little)
5869            .append_repeated(constants::DW_CFA_nop.0, 8);
5871        let instructions = instructions.get_contents().unwrap();
5872
5873        let fde = FrameDescriptionEntry {
5874            offset: 0,
5875            length: 0,
5876            format: Format::Dwarf32,
5877            cie: cie.clone(),
5878            initial_address: 0,
5879            address_range: 100,
5880            augmentation: None,
5881            instructions: EndianSlice::new(&instructions, LittleEndian),
5882        };
5883
5884        let section = &DebugFrame::from(EndianSlice::default());
5885        let bases = &BaseAddresses::default();
5886        let mut ctx = Box::new(UnwindContext::new());
5887
5888        let mut table = fde
5889            .rows(section, bases, &mut ctx)
5890            .expect("Should run initial program OK");
5891        assert!(table.ctx.is_initialized);
5892        let expected_initial_rule = (Register(0), RegisterRule::Undefined);
5893        assert_eq!(table.ctx.initial_rule, Some(expected_initial_rule));
5894
5895        {
5896            let row = table.next_row().expect("Should evaluate first row OK");
5897            let expected = UnwindTableRow {
5898                start_address: 0,
5899                end_address: 100,
5900                saved_args_size: 0,
5901                cfa: CfaRule::RegisterAndOffset {
5902                    register: Register(4),
5903                    offset: -12,
5904                },
5905                registers: [].iter().collect(),
5906            };
5907            assert_eq!(Some(&expected), row);
5908        }
5909
5910        assert_eq!(Ok(None), table.next_row());
5912        assert_eq!(Ok(None), table.next_row());
5913    }
5914
5915    #[test]
5916    fn test_unwind_table_cie_single_rule() {
5917        let initial_instructions = Section::with_endian(Endian::Little)
5918            .D8(constants::DW_CFA_def_cfa_sf.0)
5920            .uleb(4)
5921            .sleb(-12)
5922            .D8(constants::DW_CFA_offset.0 | 3)
5924            .uleb(4)
5925            .append_repeated(constants::DW_CFA_nop.0, 4);
5926        let initial_instructions = initial_instructions.get_contents().unwrap();
5927
5928        let cie = CommonInformationEntry {
5929            offset: 0,
5930            length: 0,
5931            format: Format::Dwarf32,
5932            version: 4,
5933            augmentation: None,
5934            address_size: 8,
5935            code_alignment_factor: 1,
5936            data_alignment_factor: 1,
5937            return_address_register: Register(3),
5938            initial_instructions: EndianSlice::new(&initial_instructions, LittleEndian),
5939        };
5940
5941        let instructions = Section::with_endian(Endian::Little)
5942            .append_repeated(constants::DW_CFA_nop.0, 8);
5944        let instructions = instructions.get_contents().unwrap();
5945
5946        let fde = FrameDescriptionEntry {
5947            offset: 0,
5948            length: 0,
5949            format: Format::Dwarf32,
5950            cie: cie.clone(),
5951            initial_address: 0,
5952            address_range: 100,
5953            augmentation: None,
5954            instructions: EndianSlice::new(&instructions, LittleEndian),
5955        };
5956
5957        let section = &DebugFrame::from(EndianSlice::default());
5958        let bases = &BaseAddresses::default();
5959        let mut ctx = Box::new(UnwindContext::new());
5960
5961        let mut table = fde
5962            .rows(section, bases, &mut ctx)
5963            .expect("Should run initial program OK");
5964        assert!(table.ctx.is_initialized);
5965        let expected_initial_rule = (Register(3), RegisterRule::Offset(4));
5966        assert_eq!(table.ctx.initial_rule, Some(expected_initial_rule));
5967
5968        {
5969            let row = table.next_row().expect("Should evaluate first row OK");
5970            let expected = UnwindTableRow {
5971                start_address: 0,
5972                end_address: 100,
5973                saved_args_size: 0,
5974                cfa: CfaRule::RegisterAndOffset {
5975                    register: Register(4),
5976                    offset: -12,
5977                },
5978                registers: [(Register(3), RegisterRule::Offset(4))].iter().collect(),
5979            };
5980            assert_eq!(Some(&expected), row);
5981        }
5982
5983        assert_eq!(Ok(None), table.next_row());
5985        assert_eq!(Ok(None), table.next_row());
5986    }
5987
5988    #[test]
5989    fn test_unwind_table_cie_invalid_rule() {
5990        let initial_instructions1 = Section::with_endian(Endian::Little)
5991            .D8(constants::DW_CFA_remember_state.0)
5993            .D8(constants::DW_CFA_offset.0 | 4)
5995            .uleb(8)
5996            .D8(constants::DW_CFA_offset.0);
5998        let initial_instructions1 = initial_instructions1.get_contents().unwrap();
5999
6000        let cie1 = CommonInformationEntry {
6001            offset: 0,
6002            length: 0,
6003            format: Format::Dwarf32,
6004            version: 4,
6005            augmentation: None,
6006            address_size: 8,
6007            code_alignment_factor: 1,
6008            data_alignment_factor: 1,
6009            return_address_register: Register(3),
6010            initial_instructions: EndianSlice::new(&initial_instructions1, LittleEndian),
6011        };
6012
6013        let initial_instructions2 = Section::with_endian(Endian::Little)
6014            .D8(constants::DW_CFA_offset.0 | 3)
6016            .uleb(4)
6017            .append_repeated(constants::DW_CFA_nop.0, 4);
6018        let initial_instructions2 = initial_instructions2.get_contents().unwrap();
6019
6020        let cie2 = CommonInformationEntry {
6021            offset: 0,
6022            length: 0,
6023            format: Format::Dwarf32,
6024            version: 4,
6025            augmentation: None,
6026            address_size: 8,
6027            code_alignment_factor: 1,
6028            data_alignment_factor: 1,
6029            return_address_register: Register(3),
6030            initial_instructions: EndianSlice::new(&initial_instructions2, LittleEndian),
6031        };
6032
6033        let fde1 = FrameDescriptionEntry {
6034            offset: 0,
6035            length: 0,
6036            format: Format::Dwarf32,
6037            cie: cie1.clone(),
6038            initial_address: 0,
6039            address_range: 100,
6040            augmentation: None,
6041            instructions: EndianSlice::new(&[], LittleEndian),
6042        };
6043
6044        let fde2 = FrameDescriptionEntry {
6045            offset: 0,
6046            length: 0,
6047            format: Format::Dwarf32,
6048            cie: cie2.clone(),
6049            initial_address: 0,
6050            address_range: 100,
6051            augmentation: None,
6052            instructions: EndianSlice::new(&[], LittleEndian),
6053        };
6054
6055        let section = &DebugFrame::from(EndianSlice::default());
6056        let bases = &BaseAddresses::default();
6057        let mut ctx = Box::new(UnwindContext::new());
6058
6059        let table = fde1
6060            .rows(section, bases, &mut ctx)
6061            .map_eof(&initial_instructions1);
6062        assert_eq!(table.err(), Some(Error::UnexpectedEof(ReaderOffsetId(4))));
6063        assert!(!ctx.is_initialized);
6064        assert_eq!(ctx.stack.len(), 2);
6065        assert_eq!(ctx.initial_rule, None);
6066
6067        let _table = fde2
6068            .rows(section, bases, &mut ctx)
6069            .expect("Should run initial program OK");
6070        assert!(ctx.is_initialized);
6071        assert_eq!(ctx.stack.len(), 1);
6072        let expected_initial_rule = (Register(3), RegisterRule::Offset(4));
6073        assert_eq!(ctx.initial_rule, Some(expected_initial_rule));
6074    }
6075
6076    #[test]
6077    fn test_unwind_table_next_row() {
6078        #[allow(clippy::identity_op)]
6079        let initial_instructions = Section::with_endian(Endian::Little)
6080            .D8(constants::DW_CFA_def_cfa_sf.0)
6082            .uleb(4)
6083            .sleb(-12)
6084            .D8(constants::DW_CFA_offset.0 | 0)
6086            .uleb(8)
6087            .D8(constants::DW_CFA_offset.0 | 3)
6089            .uleb(4)
6090            .append_repeated(constants::DW_CFA_nop.0, 4);
6091        let initial_instructions = initial_instructions.get_contents().unwrap();
6092
6093        let cie = CommonInformationEntry {
6094            offset: 0,
6095            length: 0,
6096            format: Format::Dwarf32,
6097            version: 4,
6098            augmentation: None,
6099            address_size: 8,
6100            code_alignment_factor: 1,
6101            data_alignment_factor: 1,
6102            return_address_register: Register(3),
6103            initial_instructions: EndianSlice::new(&initial_instructions, LittleEndian),
6104        };
6105
6106        let instructions = Section::with_endian(Endian::Little)
6107            .D8(constants::DW_CFA_advance_loc1.0)
6109            .D8(1)
6110            .D8(constants::DW_CFA_offset_extended_sf.0)
6112            .uleb(0)
6113            .sleb(-16)
6114            .D8(constants::DW_CFA_advance_loc1.0)
6116            .D8(32)
6117            .D8(constants::DW_CFA_offset_extended_sf.0)
6119            .uleb(3)
6120            .sleb(-4)
6121            .D8(constants::DW_CFA_advance_loc1.0)
6123            .D8(64)
6124            .D8(constants::DW_CFA_offset.0 | 5)
6126            .uleb(4)
6127            .append_repeated(constants::DW_CFA_nop.0, 8);
6129        let instructions = instructions.get_contents().unwrap();
6130
6131        let fde = FrameDescriptionEntry {
6132            offset: 0,
6133            length: 0,
6134            format: Format::Dwarf32,
6135            cie: cie.clone(),
6136            initial_address: 0,
6137            address_range: 100,
6138            augmentation: None,
6139            instructions: EndianSlice::new(&instructions, LittleEndian),
6140        };
6141
6142        let section = &DebugFrame::from(EndianSlice::default());
6143        let bases = &BaseAddresses::default();
6144        let mut ctx = Box::new(UnwindContext::new());
6145
6146        let mut table = fde
6147            .rows(section, bases, &mut ctx)
6148            .expect("Should run initial program OK");
6149        assert!(table.ctx.is_initialized);
6150        assert!(table.ctx.initial_rule.is_none());
6151        let expected_initial_rules: RegisterRuleMap<_> = [
6152            (Register(0), RegisterRule::Offset(8)),
6153            (Register(3), RegisterRule::Offset(4)),
6154        ]
6155        .iter()
6156        .collect();
6157        assert_eq!(table.ctx.stack[0].registers, expected_initial_rules);
6158
6159        {
6160            let row = table.next_row().expect("Should evaluate first row OK");
6161            let expected = UnwindTableRow {
6162                start_address: 0,
6163                end_address: 1,
6164                saved_args_size: 0,
6165                cfa: CfaRule::RegisterAndOffset {
6166                    register: Register(4),
6167                    offset: -12,
6168                },
6169                registers: [
6170                    (Register(0), RegisterRule::Offset(8)),
6171                    (Register(3), RegisterRule::Offset(4)),
6172                ]
6173                .iter()
6174                .collect(),
6175            };
6176            assert_eq!(Some(&expected), row);
6177        }
6178
6179        {
6180            let row = table.next_row().expect("Should evaluate second row OK");
6181            let expected = UnwindTableRow {
6182                start_address: 1,
6183                end_address: 33,
6184                saved_args_size: 0,
6185                cfa: CfaRule::RegisterAndOffset {
6186                    register: Register(4),
6187                    offset: -12,
6188                },
6189                registers: [
6190                    (Register(0), RegisterRule::Offset(-16)),
6191                    (Register(3), RegisterRule::Offset(4)),
6192                ]
6193                .iter()
6194                .collect(),
6195            };
6196            assert_eq!(Some(&expected), row);
6197        }
6198
6199        {
6200            let row = table.next_row().expect("Should evaluate third row OK");
6201            let expected = UnwindTableRow {
6202                start_address: 33,
6203                end_address: 97,
6204                saved_args_size: 0,
6205                cfa: CfaRule::RegisterAndOffset {
6206                    register: Register(4),
6207                    offset: -12,
6208                },
6209                registers: [
6210                    (Register(0), RegisterRule::Offset(-16)),
6211                    (Register(3), RegisterRule::Offset(-4)),
6212                ]
6213                .iter()
6214                .collect(),
6215            };
6216            assert_eq!(Some(&expected), row);
6217        }
6218
6219        {
6220            let row = table.next_row().expect("Should evaluate fourth row OK");
6221            let expected = UnwindTableRow {
6222                start_address: 97,
6223                end_address: 100,
6224                saved_args_size: 0,
6225                cfa: CfaRule::RegisterAndOffset {
6226                    register: Register(4),
6227                    offset: -12,
6228                },
6229                registers: [
6230                    (Register(0), RegisterRule::Offset(-16)),
6231                    (Register(3), RegisterRule::Offset(-4)),
6232                    (Register(5), RegisterRule::Offset(4)),
6233                ]
6234                .iter()
6235                .collect(),
6236            };
6237            assert_eq!(Some(&expected), row);
6238        }
6239
6240        assert_eq!(Ok(None), table.next_row());
6242        assert_eq!(Ok(None), table.next_row());
6243    }
6244
6245    #[test]
6246    fn test_unwind_info_for_address_ok() {
6247        let instrs1 = Section::with_endian(Endian::Big)
6248            .D8(constants::DW_CFA_def_cfa_sf.0)
6250            .uleb(4)
6251            .sleb(-12);
6252        let instrs1 = instrs1.get_contents().unwrap();
6253
6254        let instrs2: Vec<_> = (0..8).map(|_| constants::DW_CFA_nop.0).collect();
6255
6256        let instrs3 = Section::with_endian(Endian::Big)
6257            .D8(constants::DW_CFA_advance_loc1.0)
6259            .D8(100)
6260            .D8(constants::DW_CFA_offset_extended_sf.0)
6262            .uleb(0)
6263            .sleb(-16);
6264        let instrs3 = instrs3.get_contents().unwrap();
6265
6266        let instrs4: Vec<_> = (0..16).map(|_| constants::DW_CFA_nop.0).collect();
6267
6268        let mut cie1 = CommonInformationEntry {
6269            offset: 0,
6270            length: 0,
6271            format: Format::Dwarf32,
6272            version: 4,
6273            augmentation: None,
6274            address_size: 8,
6275            code_alignment_factor: 1,
6276            data_alignment_factor: 1,
6277            return_address_register: Register(3),
6278            initial_instructions: EndianSlice::new(&instrs1, BigEndian),
6279        };
6280
6281        let mut cie2 = CommonInformationEntry {
6282            offset: 0,
6283            length: 0,
6284            format: Format::Dwarf32,
6285            version: 4,
6286            augmentation: None,
6287            address_size: 4,
6288            code_alignment_factor: 1,
6289            data_alignment_factor: 1,
6290            return_address_register: Register(1),
6291            initial_instructions: EndianSlice::new(&instrs2, BigEndian),
6292        };
6293
6294        let cie1_location = Label::new();
6295        let cie2_location = Label::new();
6296
6297        let kind = debug_frame_be();
6301        let section = Section::with_endian(kind.endian())
6302            .mark(&cie1_location)
6303            .cie(kind, None, &mut cie1)
6304            .mark(&cie2_location)
6305            .cie(kind, None, &mut cie2);
6306
6307        let mut fde1 = FrameDescriptionEntry {
6308            offset: 0,
6309            length: 0,
6310            format: Format::Dwarf32,
6311            cie: cie1.clone(),
6312            initial_address: 0xfeed_beef,
6313            address_range: 200,
6314            augmentation: None,
6315            instructions: EndianSlice::new(&instrs3, BigEndian),
6316        };
6317
6318        let mut fde2 = FrameDescriptionEntry {
6319            offset: 0,
6320            length: 0,
6321            format: Format::Dwarf32,
6322            cie: cie2.clone(),
6323            initial_address: 0xfeed_face,
6324            address_range: 9000,
6325            augmentation: None,
6326            instructions: EndianSlice::new(&instrs4, BigEndian),
6327        };
6328
6329        let section =
6330            section
6331                .fde(kind, &cie1_location, &mut fde1)
6332                .fde(kind, &cie2_location, &mut fde2);
6333        section.start().set_const(0);
6334
6335        let contents = section.get_contents().unwrap();
6336        let debug_frame = kind.section(&contents);
6337
6338        let bases = Default::default();
6340        let mut ctx = Box::new(UnwindContext::new());
6341        let result = debug_frame.unwind_info_for_address(
6342            &bases,
6343            &mut ctx,
6344            0xfeed_beef + 150,
6345            DebugFrame::cie_from_offset,
6346        );
6347        assert!(result.is_ok());
6348        let unwind_info = result.unwrap();
6349
6350        assert_eq!(
6351            *unwind_info,
6352            UnwindTableRow {
6353                start_address: fde1.initial_address() + 100,
6354                end_address: fde1.end_address(),
6355                saved_args_size: 0,
6356                cfa: CfaRule::RegisterAndOffset {
6357                    register: Register(4),
6358                    offset: -12,
6359                },
6360                registers: [(Register(0), RegisterRule::Offset(-16))].iter().collect(),
6361            }
6362        );
6363    }
6364
6365    #[test]
6366    fn test_unwind_info_for_address_not_found() {
6367        let debug_frame = DebugFrame::new(&[], NativeEndian);
6368        let bases = Default::default();
6369        let mut ctx = Box::new(UnwindContext::new());
6370        let result = debug_frame.unwind_info_for_address(
6371            &bases,
6372            &mut ctx,
6373            0xbadb_ad99,
6374            DebugFrame::cie_from_offset,
6375        );
6376        assert!(result.is_err());
6377        assert_eq!(result.unwrap_err(), Error::NoUnwindInfoForAddress);
6378    }
6379
6380    #[test]
6381    fn test_eh_frame_hdr_unknown_version() {
6382        let bases = BaseAddresses::default();
6383        let buf = &[42];
6384        let result = EhFrameHdr::new(buf, NativeEndian).parse(&bases, 8);
6385        assert!(result.is_err());
6386        assert_eq!(result.unwrap_err(), Error::UnknownVersion(42));
6387    }
6388
6389    #[test]
6390    fn test_eh_frame_hdr_omit_ehptr() {
6391        let section = Section::with_endian(Endian::Little)
6392            .L8(1)
6393            .L8(0xff)
6394            .L8(0x03)
6395            .L8(0x0b)
6396            .L32(2)
6397            .L32(10)
6398            .L32(1)
6399            .L32(20)
6400            .L32(2)
6401            .L32(0);
6402        let section = section.get_contents().unwrap();
6403        let bases = BaseAddresses::default();
6404        let result = EhFrameHdr::new(§ion, LittleEndian).parse(&bases, 8);
6405        assert!(result.is_err());
6406        assert_eq!(result.unwrap_err(), Error::CannotParseOmitPointerEncoding);
6407    }
6408
6409    #[test]
6410    fn test_eh_frame_hdr_omit_count() {
6411        let section = Section::with_endian(Endian::Little)
6412            .L8(1)
6413            .L8(0x0b)
6414            .L8(0xff)
6415            .L8(0x0b)
6416            .L32(0x12345);
6417        let section = section.get_contents().unwrap();
6418        let bases = BaseAddresses::default();
6419        let result = EhFrameHdr::new(§ion, LittleEndian).parse(&bases, 8);
6420        assert!(result.is_ok());
6421        let result = result.unwrap();
6422        assert_eq!(result.eh_frame_ptr(), Pointer::Direct(0x12345));
6423        assert!(result.table().is_none());
6424    }
6425
6426    #[test]
6427    fn test_eh_frame_hdr_omit_table() {
6428        let section = Section::with_endian(Endian::Little)
6429            .L8(1)
6430            .L8(0x0b)
6431            .L8(0x03)
6432            .L8(0xff)
6433            .L32(0x12345)
6434            .L32(2);
6435        let section = section.get_contents().unwrap();
6436        let bases = BaseAddresses::default();
6437        let result = EhFrameHdr::new(§ion, LittleEndian).parse(&bases, 8);
6438        assert!(result.is_ok());
6439        let result = result.unwrap();
6440        assert_eq!(result.eh_frame_ptr(), Pointer::Direct(0x12345));
6441        assert!(result.table().is_none());
6442    }
6443
6444    #[test]
6445    fn test_eh_frame_hdr_varlen_table() {
6446        let section = Section::with_endian(Endian::Little)
6447            .L8(1)
6448            .L8(0x0b)
6449            .L8(0x03)
6450            .L8(0x01)
6451            .L32(0x12345)
6452            .L32(2);
6453        let section = section.get_contents().unwrap();
6454        let bases = BaseAddresses::default();
6455        let result = EhFrameHdr::new(§ion, LittleEndian).parse(&bases, 8);
6456        assert!(result.is_ok());
6457        let result = result.unwrap();
6458        assert_eq!(result.eh_frame_ptr(), Pointer::Direct(0x12345));
6459        let table = result.table();
6460        assert!(table.is_some());
6461        let table = table.unwrap();
6462        assert_eq!(
6463            table.lookup(0, &bases),
6464            Err(Error::VariableLengthSearchTable)
6465        );
6466    }
6467
6468    #[test]
6469    fn test_eh_frame_hdr_indirect_length() {
6470        let section = Section::with_endian(Endian::Little)
6471            .L8(1)
6472            .L8(0x0b)
6473            .L8(0x83)
6474            .L8(0x0b)
6475            .L32(0x12345)
6476            .L32(2);
6477        let section = section.get_contents().unwrap();
6478        let bases = BaseAddresses::default();
6479        let result = EhFrameHdr::new(§ion, LittleEndian).parse(&bases, 8);
6480        assert!(result.is_err());
6481        assert_eq!(result.unwrap_err(), Error::UnsupportedPointerEncoding);
6482    }
6483
6484    #[test]
6485    fn test_eh_frame_hdr_indirect_ptrs() {
6486        let section = Section::with_endian(Endian::Little)
6487            .L8(1)
6488            .L8(0x8b)
6489            .L8(0x03)
6490            .L8(0x8b)
6491            .L32(0x12345)
6492            .L32(2)
6493            .L32(10)
6494            .L32(1)
6495            .L32(20)
6496            .L32(2);
6497        let section = section.get_contents().unwrap();
6498        let bases = BaseAddresses::default();
6499        let result = EhFrameHdr::new(§ion, LittleEndian).parse(&bases, 8);
6500        assert!(result.is_ok());
6501        let result = result.unwrap();
6502        assert_eq!(result.eh_frame_ptr(), Pointer::Indirect(0x12345));
6503        let table = result.table();
6504        assert!(table.is_some());
6505        let table = table.unwrap();
6506        assert_eq!(
6507            table.lookup(0, &bases),
6508            Err(Error::UnsupportedPointerEncoding)
6509        );
6510    }
6511
6512    #[test]
6513    fn test_eh_frame_hdr_good() {
6514        let section = Section::with_endian(Endian::Little)
6515            .L8(1)
6516            .L8(0x0b)
6517            .L8(0x03)
6518            .L8(0x0b)
6519            .L32(0x12345)
6520            .L32(2)
6521            .L32(10)
6522            .L32(1)
6523            .L32(20)
6524            .L32(2);
6525        let section = section.get_contents().unwrap();
6526        let bases = BaseAddresses::default();
6527        let result = EhFrameHdr::new(§ion, LittleEndian).parse(&bases, 8);
6528        assert!(result.is_ok());
6529        let result = result.unwrap();
6530        assert_eq!(result.eh_frame_ptr(), Pointer::Direct(0x12345));
6531        let table = result.table();
6532        assert!(table.is_some());
6533        let table = table.unwrap();
6534        assert_eq!(table.lookup(0, &bases), Ok(Pointer::Direct(1)));
6535        assert_eq!(table.lookup(9, &bases), Ok(Pointer::Direct(1)));
6536        assert_eq!(table.lookup(10, &bases), Ok(Pointer::Direct(1)));
6537        assert_eq!(table.lookup(11, &bases), Ok(Pointer::Direct(1)));
6538        assert_eq!(table.lookup(19, &bases), Ok(Pointer::Direct(1)));
6539        assert_eq!(table.lookup(20, &bases), Ok(Pointer::Direct(2)));
6540        assert_eq!(table.lookup(21, &bases), Ok(Pointer::Direct(2)));
6541        assert_eq!(table.lookup(100_000, &bases), Ok(Pointer::Direct(2)));
6542    }
6543
6544    #[test]
6545    fn test_eh_frame_fde_for_address_good() {
6546        let mut cie = make_test_cie();
6550        cie.format = Format::Dwarf32;
6551        cie.version = 1;
6552
6553        let start_of_cie = Label::new();
6554        let end_of_cie = Label::new();
6555
6556        let kind = eh_frame_le();
6557        let section = Section::with_endian(kind.endian())
6558            .append_repeated(0, 16)
6559            .mark(&start_of_cie)
6560            .cie(kind, None, &mut cie)
6561            .mark(&end_of_cie);
6562
6563        let mut fde1 = FrameDescriptionEntry {
6564            offset: 0,
6565            length: 0,
6566            format: Format::Dwarf32,
6567            cie: cie.clone(),
6568            initial_address: 9,
6569            address_range: 4,
6570            augmentation: None,
6571            instructions: EndianSlice::new(&[], LittleEndian),
6572        };
6573        let mut fde2 = FrameDescriptionEntry {
6574            offset: 0,
6575            length: 0,
6576            format: Format::Dwarf32,
6577            cie: cie.clone(),
6578            initial_address: 20,
6579            address_range: 8,
6580            augmentation: None,
6581            instructions: EndianSlice::new(&[], LittleEndian),
6582        };
6583
6584        let start_of_fde1 = Label::new();
6585        let start_of_fde2 = Label::new();
6586
6587        let section = section
6588            .mark(&start_of_fde1)
6590            .fde(kind, (&start_of_fde1 - &start_of_cie + 4) as u64, &mut fde1)
6591            .mark(&start_of_fde2)
6592            .fde(kind, (&start_of_fde2 - &start_of_cie + 4) as u64, &mut fde2);
6593
6594        section.start().set_const(0);
6595        let section = section.get_contents().unwrap();
6596        let eh_frame = kind.section(§ion);
6597
6598        let section = Section::with_endian(kind.endian())
6600            .L8(1)
6601            .L8(0x0b)
6602            .L8(0x03)
6603            .L8(0x0b)
6604            .L32(0x12345)
6605            .L32(2)
6606            .L32(10)
6607            .L32(0x12345 + start_of_fde1.value().unwrap() as u32)
6608            .L32(20)
6609            .L32(0x12345 + start_of_fde2.value().unwrap() as u32);
6610
6611        let section = section.get_contents().unwrap();
6612        let bases = BaseAddresses::default();
6613        let eh_frame_hdr = EhFrameHdr::new(§ion, LittleEndian).parse(&bases, 8);
6614        assert!(eh_frame_hdr.is_ok());
6615        let eh_frame_hdr = eh_frame_hdr.unwrap();
6616
6617        let table = eh_frame_hdr.table();
6618        assert!(table.is_some());
6619        let table = table.unwrap();
6620
6621        let bases = Default::default();
6622        let mut iter = table.iter(&bases);
6623        assert_eq!(
6624            iter.next(),
6625            Ok(Some((
6626                Pointer::Direct(10),
6627                Pointer::Direct(0x12345 + start_of_fde1.value().unwrap())
6628            )))
6629        );
6630        assert_eq!(
6631            iter.next(),
6632            Ok(Some((
6633                Pointer::Direct(20),
6634                Pointer::Direct(0x12345 + start_of_fde2.value().unwrap())
6635            )))
6636        );
6637        assert_eq!(iter.next(), Ok(None));
6638
6639        assert_eq!(
6640            table.iter(&bases).nth(0),
6641            Ok(Some((
6642                Pointer::Direct(10),
6643                Pointer::Direct(0x12345 + start_of_fde1.value().unwrap())
6644            )))
6645        );
6646
6647        assert_eq!(
6648            table.iter(&bases).nth(1),
6649            Ok(Some((
6650                Pointer::Direct(20),
6651                Pointer::Direct(0x12345 + start_of_fde2.value().unwrap())
6652            )))
6653        );
6654        assert_eq!(table.iter(&bases).nth(2), Ok(None));
6655
6656        let f = |_: &_, _: &_, o: EhFrameOffset| {
6657            assert_eq!(o, EhFrameOffset(start_of_cie.value().unwrap() as usize));
6658            Ok(cie.clone())
6659        };
6660        assert_eq!(
6661            table.fde_for_address(&eh_frame, &bases, 9, f),
6662            Ok(fde1.clone())
6663        );
6664        assert_eq!(
6665            table.fde_for_address(&eh_frame, &bases, 10, f),
6666            Ok(fde1.clone())
6667        );
6668        assert_eq!(table.fde_for_address(&eh_frame, &bases, 11, f), Ok(fde1));
6669        assert_eq!(
6670            table.fde_for_address(&eh_frame, &bases, 19, f),
6671            Err(Error::NoUnwindInfoForAddress)
6672        );
6673        assert_eq!(
6674            table.fde_for_address(&eh_frame, &bases, 20, f),
6675            Ok(fde2.clone())
6676        );
6677        assert_eq!(table.fde_for_address(&eh_frame, &bases, 21, f), Ok(fde2));
6678        assert_eq!(
6679            table.fde_for_address(&eh_frame, &bases, 100_000, f),
6680            Err(Error::NoUnwindInfoForAddress)
6681        );
6682    }
6683
6684    #[test]
6685    fn test_eh_frame_stops_at_zero_length() {
6686        let mut cie = make_test_cie();
6687        let kind = eh_frame_le();
6688        let section = Section::with_endian(Endian::Little)
6689            .L32(0)
6690            .cie(kind, None, &mut cie)
6691            .L32(0);
6692        let contents = section.get_contents().unwrap();
6693        let eh_frame = kind.section(&contents);
6694        let bases = Default::default();
6695
6696        let mut entries = eh_frame.entries(&bases);
6697        assert_eq!(entries.next(), Ok(None));
6698
6699        assert_eq!(
6700            eh_frame.cie_from_offset(&bases, EhFrameOffset(0)),
6701            Err(Error::NoEntryAtGivenOffset)
6702        );
6703    }
6704
6705    #[test]
6706    fn test_debug_frame_skips_zero_length() {
6707        let mut cie = make_test_cie();
6708        let kind = debug_frame_le();
6709        let section = Section::with_endian(Endian::Little)
6710            .L32(0)
6711            .cie(kind, None, &mut cie)
6712            .L32(0);
6713        let contents = section.get_contents().unwrap();
6714        let debug_frame = kind.section(&contents);
6715        let bases = Default::default();
6716
6717        let mut entries = debug_frame.entries(&bases);
6718        assert_eq!(entries.next(), Ok(Some(CieOrFde::Cie(cie))));
6719        assert_eq!(entries.next(), Ok(None));
6720
6721        assert_eq!(
6722            debug_frame.cie_from_offset(&bases, DebugFrameOffset(0)),
6723            Err(Error::NoEntryAtGivenOffset)
6724        );
6725    }
6726
6727    fn resolve_cie_offset(buf: &[u8], cie_offset: usize) -> Result<usize> {
6728        let mut fde = FrameDescriptionEntry {
6729            offset: 0,
6730            length: 0,
6731            format: Format::Dwarf64,
6732            cie: make_test_cie(),
6733            initial_address: 0xfeed_beef,
6734            address_range: 39,
6735            augmentation: None,
6736            instructions: EndianSlice::new(&[], LittleEndian),
6737        };
6738
6739        let kind = eh_frame_le();
6740        let section = Section::with_endian(kind.endian())
6741            .append_bytes(buf)
6742            .fde(kind, cie_offset as u64, &mut fde)
6743            .append_bytes(buf);
6744
6745        let section = section.get_contents().unwrap();
6746        let eh_frame = kind.section(§ion);
6747        let input = &mut EndianSlice::new(§ion[buf.len()..], LittleEndian);
6748
6749        let bases = Default::default();
6750        match parse_cfi_entry(&bases, &eh_frame, input) {
6751            Ok(Some(CieOrFde::Fde(partial))) => Ok(partial.cie_offset.0),
6752            Err(e) => Err(e),
6753            otherwise => panic!("Unexpected result: {:#?}", otherwise),
6754        }
6755    }
6756
6757    #[test]
6758    fn test_eh_frame_resolve_cie_offset_ok() {
6759        let buf = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
6760        let cie_offset = 2;
6761        assert_eq!(
6763            resolve_cie_offset(&buf, buf.len() + 4 - cie_offset),
6764            Ok(cie_offset)
6765        );
6766    }
6767
6768    #[test]
6769    fn test_eh_frame_resolve_cie_offset_out_of_bounds() {
6770        let buf = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
6771        assert_eq!(
6772            resolve_cie_offset(&buf, buf.len() + 4 + 2),
6773            Err(Error::OffsetOutOfBounds)
6774        );
6775    }
6776
6777    #[test]
6778    fn test_eh_frame_resolve_cie_offset_underflow() {
6779        let buf = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
6780        assert_eq!(
6781            resolve_cie_offset(&buf, usize::MAX),
6782            Err(Error::OffsetOutOfBounds)
6783        );
6784    }
6785
6786    #[test]
6787    fn test_eh_frame_fde_ok() {
6788        let mut cie = make_test_cie();
6789        cie.format = Format::Dwarf32;
6790        cie.version = 1;
6791
6792        let start_of_cie = Label::new();
6793        let end_of_cie = Label::new();
6794
6795        let kind = eh_frame_le();
6798        let section = Section::with_endian(kind.endian())
6799            .append_repeated(0, 16)
6800            .mark(&start_of_cie)
6801            .cie(kind, None, &mut cie)
6802            .mark(&end_of_cie);
6803
6804        let mut fde = FrameDescriptionEntry {
6805            offset: 0,
6806            length: 0,
6807            format: Format::Dwarf32,
6808            cie: cie.clone(),
6809            initial_address: 0xfeed_beef,
6810            address_range: 999,
6811            augmentation: None,
6812            instructions: EndianSlice::new(&[], LittleEndian),
6813        };
6814
6815        let section = section
6816            .fde(kind, (&end_of_cie - &start_of_cie + 4) as u64, &mut fde);
6818
6819        section.start().set_const(0);
6820        let section = section.get_contents().unwrap();
6821        let eh_frame = kind.section(§ion);
6822        let section = EndianSlice::new(§ion, LittleEndian);
6823
6824        let mut offset = None;
6825        let result = parse_fde(
6826            eh_frame,
6827            &mut section.range_from(end_of_cie.value().unwrap() as usize..),
6828            |_, _, o| {
6829                offset = Some(o);
6830                assert_eq!(o, EhFrameOffset(start_of_cie.value().unwrap() as usize));
6831                Ok(cie.clone())
6832            },
6833        );
6834        match result {
6835            Ok(actual) => assert_eq!(actual, fde),
6836            otherwise => panic!("Unexpected result {:?}", otherwise),
6837        }
6838        assert!(offset.is_some());
6839    }
6840
6841    #[test]
6842    fn test_eh_frame_fde_out_of_bounds() {
6843        let mut cie = make_test_cie();
6844        cie.version = 1;
6845
6846        let end_of_cie = Label::new();
6847
6848        let mut fde = FrameDescriptionEntry {
6849            offset: 0,
6850            length: 0,
6851            format: Format::Dwarf64,
6852            cie: cie.clone(),
6853            initial_address: 0xfeed_beef,
6854            address_range: 999,
6855            augmentation: None,
6856            instructions: EndianSlice::new(&[], LittleEndian),
6857        };
6858
6859        let kind = eh_frame_le();
6860        let section = Section::with_endian(kind.endian())
6861            .cie(kind, None, &mut cie)
6862            .mark(&end_of_cie)
6863            .fde(kind, 99_999_999_999_999, &mut fde);
6864
6865        section.start().set_const(0);
6866        let section = section.get_contents().unwrap();
6867        let eh_frame = kind.section(§ion);
6868        let section = EndianSlice::new(§ion, LittleEndian);
6869
6870        let result = parse_fde(
6871            eh_frame,
6872            &mut section.range_from(end_of_cie.value().unwrap() as usize..),
6873            UnwindSection::cie_from_offset,
6874        );
6875        assert_eq!(result, Err(Error::OffsetOutOfBounds));
6876    }
6877
6878    #[test]
6879    fn test_augmentation_parse_not_z_augmentation() {
6880        let augmentation = &mut EndianSlice::new(b"wtf", NativeEndian);
6881        let bases = Default::default();
6882        let address_size = 8;
6883        let section = EhFrame::new(&[], NativeEndian);
6884        let input = &mut EndianSlice::new(&[], NativeEndian);
6885        assert_eq!(
6886            Augmentation::parse(augmentation, &bases, address_size, §ion, input),
6887            Err(Error::UnknownAugmentation)
6888        );
6889    }
6890
6891    #[test]
6892    fn test_augmentation_parse_just_signal_trampoline() {
6893        let aug_str = &mut EndianSlice::new(b"S", LittleEndian);
6894        let bases = Default::default();
6895        let address_size = 8;
6896        let section = EhFrame::new(&[], LittleEndian);
6897        let input = &mut EndianSlice::new(&[], LittleEndian);
6898
6899        let augmentation = Augmentation {
6900            is_signal_trampoline: true,
6901            ..Default::default()
6902        };
6903
6904        assert_eq!(
6905            Augmentation::parse(aug_str, &bases, address_size, §ion, input),
6906            Ok(augmentation)
6907        );
6908    }
6909
6910    #[test]
6911    fn test_augmentation_parse_unknown_part_of_z_augmentation() {
6912        let bases = Default::default();
6914        let address_size = 8;
6915        let section = Section::with_endian(Endian::Little)
6916            .uleb(4)
6917            .append_repeated(4, 4)
6918            .get_contents()
6919            .unwrap();
6920        let section = EhFrame::new(§ion, LittleEndian);
6921        let input = &mut section.section().clone();
6922        let augmentation = &mut EndianSlice::new(b"zZ", LittleEndian);
6923        assert_eq!(
6924            Augmentation::parse(augmentation, &bases, address_size, §ion, input),
6925            Err(Error::UnknownAugmentation)
6926        );
6927    }
6928
6929    #[test]
6930    #[allow(non_snake_case)]
6931    fn test_augmentation_parse_L() {
6932        let bases = Default::default();
6933        let address_size = 8;
6934        let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1];
6935
6936        let section = Section::with_endian(Endian::Little)
6937            .uleb(1)
6938            .D8(constants::DW_EH_PE_uleb128.0)
6939            .append_bytes(&rest)
6940            .get_contents()
6941            .unwrap();
6942        let section = EhFrame::new(§ion, LittleEndian);
6943        let input = &mut section.section().clone();
6944        let aug_str = &mut EndianSlice::new(b"zL", LittleEndian);
6945
6946        let augmentation = Augmentation {
6947            lsda: Some(constants::DW_EH_PE_uleb128),
6948            ..Default::default()
6949        };
6950
6951        assert_eq!(
6952            Augmentation::parse(aug_str, &bases, address_size, §ion, input),
6953            Ok(augmentation)
6954        );
6955        assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
6956    }
6957
6958    #[test]
6959    #[allow(non_snake_case)]
6960    fn test_augmentation_parse_P() {
6961        let bases = Default::default();
6962        let address_size = 8;
6963        let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1];
6964
6965        let section = Section::with_endian(Endian::Little)
6966            .uleb(9)
6967            .D8(constants::DW_EH_PE_udata8.0)
6968            .L64(0xf00d_f00d)
6969            .append_bytes(&rest)
6970            .get_contents()
6971            .unwrap();
6972        let section = EhFrame::new(§ion, LittleEndian);
6973        let input = &mut section.section().clone();
6974        let aug_str = &mut EndianSlice::new(b"zP", LittleEndian);
6975
6976        let augmentation = Augmentation {
6977            personality: Some((constants::DW_EH_PE_udata8, Pointer::Direct(0xf00d_f00d))),
6978            ..Default::default()
6979        };
6980
6981        assert_eq!(
6982            Augmentation::parse(aug_str, &bases, address_size, §ion, input),
6983            Ok(augmentation)
6984        );
6985        assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
6986    }
6987
6988    #[test]
6989    #[allow(non_snake_case)]
6990    fn test_augmentation_parse_R() {
6991        let bases = Default::default();
6992        let address_size = 8;
6993        let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1];
6994
6995        let section = Section::with_endian(Endian::Little)
6996            .uleb(1)
6997            .D8(constants::DW_EH_PE_udata4.0)
6998            .append_bytes(&rest)
6999            .get_contents()
7000            .unwrap();
7001        let section = EhFrame::new(§ion, LittleEndian);
7002        let input = &mut section.section().clone();
7003        let aug_str = &mut EndianSlice::new(b"zR", LittleEndian);
7004
7005        let augmentation = Augmentation {
7006            fde_address_encoding: Some(constants::DW_EH_PE_udata4),
7007            ..Default::default()
7008        };
7009
7010        assert_eq!(
7011            Augmentation::parse(aug_str, &bases, address_size, §ion, input),
7012            Ok(augmentation)
7013        );
7014        assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
7015    }
7016
7017    #[test]
7018    #[allow(non_snake_case)]
7019    fn test_augmentation_parse_S() {
7020        let bases = Default::default();
7021        let address_size = 8;
7022        let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1];
7023
7024        let section = Section::with_endian(Endian::Little)
7025            .uleb(0)
7026            .append_bytes(&rest)
7027            .get_contents()
7028            .unwrap();
7029        let section = EhFrame::new(§ion, LittleEndian);
7030        let input = &mut section.section().clone();
7031        let aug_str = &mut EndianSlice::new(b"zS", LittleEndian);
7032
7033        let augmentation = Augmentation {
7034            is_signal_trampoline: true,
7035            ..Default::default()
7036        };
7037
7038        assert_eq!(
7039            Augmentation::parse(aug_str, &bases, address_size, §ion, input),
7040            Ok(augmentation)
7041        );
7042        assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
7043    }
7044
7045    #[test]
7046    fn test_augmentation_parse_all() {
7047        let bases = Default::default();
7048        let address_size = 8;
7049        let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1];
7050
7051        let section = Section::with_endian(Endian::Little)
7052            .uleb(1 + 9 + 1)
7053            .D8(constants::DW_EH_PE_uleb128.0)
7055            .D8(constants::DW_EH_PE_udata8.0)
7057            .L64(0x1bad_f00d)
7058            .D8(constants::DW_EH_PE_uleb128.0)
7060            .append_bytes(&rest)
7061            .get_contents()
7062            .unwrap();
7063        let section = EhFrame::new(§ion, LittleEndian);
7064        let input = &mut section.section().clone();
7065        let aug_str = &mut EndianSlice::new(b"zLPRS", LittleEndian);
7066
7067        let augmentation = Augmentation {
7068            lsda: Some(constants::DW_EH_PE_uleb128),
7069            personality: Some((constants::DW_EH_PE_udata8, Pointer::Direct(0x1bad_f00d))),
7070            fde_address_encoding: Some(constants::DW_EH_PE_uleb128),
7071            is_signal_trampoline: true,
7072        };
7073
7074        assert_eq!(
7075            Augmentation::parse(aug_str, &bases, address_size, §ion, input),
7076            Ok(augmentation)
7077        );
7078        assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
7079    }
7080
7081    #[test]
7082    fn test_eh_frame_fde_no_augmentation() {
7083        let instrs = [1, 2, 3, 4];
7084        let cie_offset = 1;
7085
7086        let mut cie = make_test_cie();
7087        cie.format = Format::Dwarf32;
7088        cie.version = 1;
7089
7090        let mut fde = FrameDescriptionEntry {
7091            offset: 0,
7092            length: 0,
7093            format: Format::Dwarf32,
7094            cie: cie.clone(),
7095            initial_address: 0xfeed_face,
7096            address_range: 9000,
7097            augmentation: None,
7098            instructions: EndianSlice::new(&instrs, LittleEndian),
7099        };
7100
7101        let rest = [1, 2, 3, 4];
7102
7103        let kind = eh_frame_le();
7104        let section = Section::with_endian(kind.endian())
7105            .fde(kind, cie_offset, &mut fde)
7106            .append_bytes(&rest)
7107            .get_contents()
7108            .unwrap();
7109        let section = kind.section(§ion);
7110        let input = &mut section.section().clone();
7111
7112        let result = parse_fde(section, input, |_, _, _| Ok(cie.clone()));
7113        assert_eq!(result, Ok(fde));
7114        assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
7115    }
7116
7117    #[test]
7118    fn test_eh_frame_fde_empty_augmentation() {
7119        let instrs = [1, 2, 3, 4];
7120        let cie_offset = 1;
7121
7122        let mut cie = make_test_cie();
7123        cie.format = Format::Dwarf32;
7124        cie.version = 1;
7125        cie.augmentation = Some(Augmentation::default());
7126
7127        let mut fde = FrameDescriptionEntry {
7128            offset: 0,
7129            length: 0,
7130            format: Format::Dwarf32,
7131            cie: cie.clone(),
7132            initial_address: 0xfeed_face,
7133            address_range: 9000,
7134            augmentation: Some(AugmentationData::default()),
7135            instructions: EndianSlice::new(&instrs, LittleEndian),
7136        };
7137
7138        let rest = [1, 2, 3, 4];
7139
7140        let kind = eh_frame_le();
7141        let section = Section::with_endian(kind.endian())
7142            .fde(kind, cie_offset, &mut fde)
7143            .append_bytes(&rest)
7144            .get_contents()
7145            .unwrap();
7146        let section = kind.section(§ion);
7147        let input = &mut section.section().clone();
7148
7149        let result = parse_fde(section, input, |_, _, _| Ok(cie.clone()));
7150        assert_eq!(result, Ok(fde));
7151        assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
7152    }
7153
7154    #[test]
7155    fn test_eh_frame_fde_lsda_augmentation() {
7156        let instrs = [1, 2, 3, 4];
7157        let cie_offset = 1;
7158
7159        let mut cie = make_test_cie();
7160        cie.format = Format::Dwarf32;
7161        cie.version = 1;
7162        cie.augmentation = Some(Augmentation::default());
7163        cie.augmentation.as_mut().unwrap().lsda = Some(constants::DW_EH_PE_absptr);
7164
7165        let mut fde = FrameDescriptionEntry {
7166            offset: 0,
7167            length: 0,
7168            format: Format::Dwarf32,
7169            cie: cie.clone(),
7170            initial_address: 0xfeed_face,
7171            address_range: 9000,
7172            augmentation: Some(AugmentationData {
7173                lsda: Some(Pointer::Direct(0x1122_3344)),
7174            }),
7175            instructions: EndianSlice::new(&instrs, LittleEndian),
7176        };
7177
7178        let rest = [1, 2, 3, 4];
7179
7180        let kind = eh_frame_le();
7181        let section = Section::with_endian(kind.endian())
7182            .fde(kind, cie_offset, &mut fde)
7183            .append_bytes(&rest)
7184            .get_contents()
7185            .unwrap();
7186        let section = kind.section(§ion);
7187        let input = &mut section.section().clone();
7188
7189        let result = parse_fde(section, input, |_, _, _| Ok(cie.clone()));
7190        assert_eq!(result, Ok(fde));
7191        assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
7192    }
7193
7194    #[test]
7195    fn test_eh_frame_fde_lsda_function_relative() {
7196        let instrs = [1, 2, 3, 4];
7197        let cie_offset = 1;
7198
7199        let mut cie = make_test_cie();
7200        cie.format = Format::Dwarf32;
7201        cie.version = 1;
7202        cie.augmentation = Some(Augmentation::default());
7203        cie.augmentation.as_mut().unwrap().lsda =
7204            Some(constants::DW_EH_PE_funcrel | constants::DW_EH_PE_absptr);
7205
7206        let mut fde = FrameDescriptionEntry {
7207            offset: 0,
7208            length: 0,
7209            format: Format::Dwarf32,
7210            cie: cie.clone(),
7211            initial_address: 0xfeed_face,
7212            address_range: 9000,
7213            augmentation: Some(AugmentationData {
7214                lsda: Some(Pointer::Direct(0xbeef)),
7215            }),
7216            instructions: EndianSlice::new(&instrs, LittleEndian),
7217        };
7218
7219        let rest = [1, 2, 3, 4];
7220
7221        let kind = eh_frame_le();
7222        let section = Section::with_endian(kind.endian())
7223            .append_repeated(10, 10)
7224            .fde(kind, cie_offset, &mut fde)
7225            .append_bytes(&rest)
7226            .get_contents()
7227            .unwrap();
7228        let section = kind.section(§ion);
7229        let input = &mut section.section().range_from(10..);
7230
7231        fde.augmentation.as_mut().unwrap().lsda = Some(Pointer::Direct(0xfeed_face + 0xbeef));
7233
7234        let result = parse_fde(section, input, |_, _, _| Ok(cie.clone()));
7235        assert_eq!(result, Ok(fde));
7236        assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
7237    }
7238
7239    #[test]
7240    fn test_eh_frame_cie_personality_function_relative_bad_context() {
7241        let instrs = [1, 2, 3, 4];
7242
7243        let length = Label::new();
7244        let start = Label::new();
7245        let end = Label::new();
7246
7247        let aug_len = Label::new();
7248        let aug_start = Label::new();
7249        let aug_end = Label::new();
7250
7251        let section = Section::with_endian(Endian::Little)
7252            .L32(&length)
7254            .mark(&start)
7255            .L32(0)
7257            .D8(1)
7259            .append_bytes(b"zP\0")
7261            .uleb(1)
7263            .sleb(1)
7265            .uleb(1)
7267            .D8(&aug_len)
7271            .mark(&aug_start)
7272            .D8(constants::DW_EH_PE_funcrel.0 | constants::DW_EH_PE_uleb128.0)
7274            .uleb(1)
7275            .mark(&aug_end)
7276            .append_bytes(&instrs)
7278            .mark(&end);
7279
7280        length.set_const((&end - &start) as u64);
7281        aug_len.set_const((&aug_end - &aug_start) as u64);
7282
7283        let section = section.get_contents().unwrap();
7284        let section = EhFrame::new(§ion, LittleEndian);
7285
7286        let bases = BaseAddresses::default();
7287        let mut iter = section.entries(&bases);
7288        assert_eq!(iter.next(), Err(Error::FuncRelativePointerInBadContext));
7289    }
7290
7291    #[test]
7292    fn register_rule_map_eq() {
7293        let map1: RegisterRuleMap<usize> = [
7295            (Register(0), RegisterRule::SameValue),
7296            (Register(3), RegisterRule::Offset(1)),
7297        ]
7298        .iter()
7299        .collect();
7300        let map2: RegisterRuleMap<usize> = [
7301            (Register(3), RegisterRule::Offset(1)),
7302            (Register(0), RegisterRule::SameValue),
7303        ]
7304        .iter()
7305        .collect();
7306        assert_eq!(map1, map2);
7307        assert_eq!(map2, map1);
7308
7309        let map3: RegisterRuleMap<usize> = [
7311            (Register(0), RegisterRule::SameValue),
7312            (Register(2), RegisterRule::Offset(1)),
7313        ]
7314        .iter()
7315        .collect();
7316        let map4: RegisterRuleMap<usize> = [
7317            (Register(3), RegisterRule::Offset(1)),
7318            (Register(0), RegisterRule::SameValue),
7319        ]
7320        .iter()
7321        .collect();
7322        assert!(map3 != map4);
7323        assert!(map4 != map3);
7324
7325        let mut map5 = RegisterRuleMap::<usize>::default();
7327        map5.set(Register(0), RegisterRule::SameValue).unwrap();
7328        map5.set(Register(0), RegisterRule::Undefined).unwrap();
7329        let map6 = RegisterRuleMap::<usize>::default();
7330        assert_eq!(map5, map6);
7331        assert_eq!(map6, map5);
7332    }
7333
7334    #[test]
7335    fn iter_register_rules() {
7336        let row = UnwindTableRow::<usize> {
7337            registers: [
7338                (Register(0), RegisterRule::SameValue),
7339                (Register(1), RegisterRule::Offset(1)),
7340                (Register(2), RegisterRule::ValOffset(2)),
7341            ]
7342            .iter()
7343            .collect(),
7344            ..Default::default()
7345        };
7346
7347        let mut found0 = false;
7348        let mut found1 = false;
7349        let mut found2 = false;
7350
7351        for &(register, ref rule) in row.registers() {
7352            match register.0 {
7353                0 => {
7354                    assert!(!found0);
7355                    found0 = true;
7356                    assert_eq!(*rule, RegisterRule::SameValue);
7357                }
7358                1 => {
7359                    assert!(!found1);
7360                    found1 = true;
7361                    assert_eq!(*rule, RegisterRule::Offset(1));
7362                }
7363                2 => {
7364                    assert!(!found2);
7365                    found2 = true;
7366                    assert_eq!(*rule, RegisterRule::ValOffset(2));
7367                }
7368                x => panic!("Unexpected register rule: ({}, {:?})", x, rule),
7369            }
7370        }
7371
7372        assert!(found0);
7373        assert!(found1);
7374        assert!(found2);
7375    }
7376
7377    #[test]
7378    #[cfg(target_pointer_width = "64")]
7379    fn size_of_unwind_ctx() {
7380        use core::mem;
7381        let size = mem::size_of::<UnwindContext<usize>>();
7382        let max_size = 30968;
7383        if size > max_size {
7384            assert_eq!(size, max_size);
7385        }
7386    }
7387
7388    #[test]
7389    #[cfg(target_pointer_width = "64")]
7390    fn size_of_register_rule_map() {
7391        use core::mem;
7392        let size = mem::size_of::<RegisterRuleMap<usize>>();
7393        let max_size = 6152;
7394        if size > max_size {
7395            assert_eq!(size, max_size);
7396        }
7397    }
7398
7399    #[test]
7400    fn test_parse_pointer_encoding_ok() {
7401        use crate::endianity::NativeEndian;
7402        let expected = constants::DW_EH_PE_uleb128 | constants::DW_EH_PE_pcrel;
7403        let input = [expected.0, 1, 2, 3, 4];
7404        let input = &mut EndianSlice::new(&input, NativeEndian);
7405        assert_eq!(parse_pointer_encoding(input), Ok(expected));
7406        assert_eq!(*input, EndianSlice::new(&[1, 2, 3, 4], NativeEndian));
7407    }
7408
7409    #[test]
7410    fn test_parse_pointer_encoding_bad_encoding() {
7411        use crate::endianity::NativeEndian;
7412        let expected =
7413            constants::DwEhPe((constants::DW_EH_PE_sdata8.0 + 1) | constants::DW_EH_PE_pcrel.0);
7414        let input = [expected.0, 1, 2, 3, 4];
7415        let input = &mut EndianSlice::new(&input, NativeEndian);
7416        assert_eq!(
7417            Err(Error::UnknownPointerEncoding(expected)),
7418            parse_pointer_encoding(input)
7419        );
7420    }
7421
7422    #[test]
7423    fn test_parse_encoded_pointer_absptr() {
7424        let encoding = constants::DW_EH_PE_absptr;
7425        let expected_rest = [1, 2, 3, 4];
7426
7427        let input = Section::with_endian(Endian::Little)
7428            .L32(0xf00d_f00d)
7429            .append_bytes(&expected_rest);
7430        let input = input.get_contents().unwrap();
7431        let input = EndianSlice::new(&input, LittleEndian);
7432        let mut rest = input;
7433
7434        let parameters = PointerEncodingParameters {
7435            bases: &SectionBaseAddresses::default(),
7436            func_base: None,
7437            address_size: 4,
7438            section: &input,
7439        };
7440        assert_eq!(
7441            parse_encoded_pointer(encoding, ¶meters, &mut rest),
7442            Ok(Pointer::Direct(0xf00d_f00d))
7443        );
7444        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7445    }
7446
7447    #[test]
7448    fn test_parse_encoded_pointer_pcrel() {
7449        let encoding = constants::DW_EH_PE_pcrel;
7450        let expected_rest = [1, 2, 3, 4];
7451
7452        let input = Section::with_endian(Endian::Little)
7453            .append_repeated(0, 0x10)
7454            .L32(0x1)
7455            .append_bytes(&expected_rest);
7456        let input = input.get_contents().unwrap();
7457        let input = EndianSlice::new(&input, LittleEndian);
7458        let mut rest = input.range_from(0x10..);
7459
7460        let parameters = PointerEncodingParameters {
7461            bases: &BaseAddresses::default().set_eh_frame(0x100).eh_frame,
7462            func_base: None,
7463            address_size: 4,
7464            section: &input,
7465        };
7466        assert_eq!(
7467            parse_encoded_pointer(encoding, ¶meters, &mut rest),
7468            Ok(Pointer::Direct(0x111))
7469        );
7470        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7471    }
7472
7473    #[test]
7474    fn test_parse_encoded_pointer_pcrel_undefined() {
7475        let encoding = constants::DW_EH_PE_pcrel;
7476
7477        let input = Section::with_endian(Endian::Little).L32(0x1);
7478        let input = input.get_contents().unwrap();
7479        let input = EndianSlice::new(&input, LittleEndian);
7480        let mut rest = input;
7481
7482        let parameters = PointerEncodingParameters {
7483            bases: &SectionBaseAddresses::default(),
7484            func_base: None,
7485            address_size: 4,
7486            section: &input,
7487        };
7488        assert_eq!(
7489            parse_encoded_pointer(encoding, ¶meters, &mut rest),
7490            Err(Error::PcRelativePointerButSectionBaseIsUndefined)
7491        );
7492    }
7493
7494    #[test]
7495    fn test_parse_encoded_pointer_textrel() {
7496        let encoding = constants::DW_EH_PE_textrel;
7497        let expected_rest = [1, 2, 3, 4];
7498
7499        let input = Section::with_endian(Endian::Little)
7500            .L32(0x1)
7501            .append_bytes(&expected_rest);
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: &BaseAddresses::default().set_text(0x10).eh_frame,
7508            func_base: None,
7509            address_size: 4,
7510            section: &input,
7511        };
7512        assert_eq!(
7513            parse_encoded_pointer(encoding, ¶meters, &mut rest),
7514            Ok(Pointer::Direct(0x11))
7515        );
7516        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7517    }
7518
7519    #[test]
7520    fn test_parse_encoded_pointer_textrel_undefined() {
7521        let encoding = constants::DW_EH_PE_textrel;
7522
7523        let input = Section::with_endian(Endian::Little).L32(0x1);
7524        let input = input.get_contents().unwrap();
7525        let input = EndianSlice::new(&input, LittleEndian);
7526        let mut rest = input;
7527
7528        let parameters = PointerEncodingParameters {
7529            bases: &SectionBaseAddresses::default(),
7530            func_base: None,
7531            address_size: 4,
7532            section: &input,
7533        };
7534        assert_eq!(
7535            parse_encoded_pointer(encoding, ¶meters, &mut rest),
7536            Err(Error::TextRelativePointerButTextBaseIsUndefined)
7537        );
7538    }
7539
7540    #[test]
7541    fn test_parse_encoded_pointer_datarel() {
7542        let encoding = constants::DW_EH_PE_datarel;
7543        let expected_rest = [1, 2, 3, 4];
7544
7545        let input = Section::with_endian(Endian::Little)
7546            .L32(0x1)
7547            .append_bytes(&expected_rest);
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: &BaseAddresses::default().set_got(0x10).eh_frame,
7554            func_base: None,
7555            address_size: 4,
7556            section: &input,
7557        };
7558        assert_eq!(
7559            parse_encoded_pointer(encoding, ¶meters, &mut rest),
7560            Ok(Pointer::Direct(0x11))
7561        );
7562        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7563    }
7564
7565    #[test]
7566    fn test_parse_encoded_pointer_datarel_undefined() {
7567        let encoding = constants::DW_EH_PE_datarel;
7568
7569        let input = Section::with_endian(Endian::Little).L32(0x1);
7570        let input = input.get_contents().unwrap();
7571        let input = EndianSlice::new(&input, LittleEndian);
7572        let mut rest = input;
7573
7574        let parameters = PointerEncodingParameters {
7575            bases: &SectionBaseAddresses::default(),
7576            func_base: None,
7577            address_size: 4,
7578            section: &input,
7579        };
7580        assert_eq!(
7581            parse_encoded_pointer(encoding, ¶meters, &mut rest),
7582            Err(Error::DataRelativePointerButDataBaseIsUndefined)
7583        );
7584    }
7585
7586    #[test]
7587    fn test_parse_encoded_pointer_funcrel() {
7588        let encoding = constants::DW_EH_PE_funcrel;
7589        let expected_rest = [1, 2, 3, 4];
7590
7591        let input = Section::with_endian(Endian::Little)
7592            .L32(0x1)
7593            .append_bytes(&expected_rest);
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: Some(0x10),
7601            address_size: 4,
7602            section: &input,
7603        };
7604        assert_eq!(
7605            parse_encoded_pointer(encoding, ¶meters, &mut rest),
7606            Ok(Pointer::Direct(0x11))
7607        );
7608        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7609    }
7610
7611    #[test]
7612    fn test_parse_encoded_pointer_funcrel_undefined() {
7613        let encoding = constants::DW_EH_PE_funcrel;
7614
7615        let input = Section::with_endian(Endian::Little).L32(0x1);
7616        let input = input.get_contents().unwrap();
7617        let input = EndianSlice::new(&input, LittleEndian);
7618        let mut rest = input;
7619
7620        let parameters = PointerEncodingParameters {
7621            bases: &SectionBaseAddresses::default(),
7622            func_base: None,
7623            address_size: 4,
7624            section: &input,
7625        };
7626        assert_eq!(
7627            parse_encoded_pointer(encoding, ¶meters, &mut rest),
7628            Err(Error::FuncRelativePointerInBadContext)
7629        );
7630    }
7631
7632    #[test]
7633    fn test_parse_encoded_pointer_uleb128() {
7634        let encoding = constants::DW_EH_PE_absptr | constants::DW_EH_PE_uleb128;
7635        let expected_rest = [1, 2, 3, 4];
7636
7637        let input = Section::with_endian(Endian::Little)
7638            .uleb(0x12_3456)
7639            .append_bytes(&expected_rest);
7640        let input = input.get_contents().unwrap();
7641        let input = EndianSlice::new(&input, LittleEndian);
7642        let mut rest = input;
7643
7644        let parameters = PointerEncodingParameters {
7645            bases: &SectionBaseAddresses::default(),
7646            func_base: None,
7647            address_size: 4,
7648            section: &input,
7649        };
7650        assert_eq!(
7651            parse_encoded_pointer(encoding, ¶meters, &mut rest),
7652            Ok(Pointer::Direct(0x12_3456))
7653        );
7654        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7655    }
7656
7657    #[test]
7658    fn test_parse_encoded_pointer_udata2() {
7659        let encoding = constants::DW_EH_PE_absptr | constants::DW_EH_PE_udata2;
7660        let expected_rest = [1, 2, 3, 4];
7661
7662        let input = Section::with_endian(Endian::Little)
7663            .L16(0x1234)
7664            .append_bytes(&expected_rest);
7665        let input = input.get_contents().unwrap();
7666        let input = EndianSlice::new(&input, LittleEndian);
7667        let mut rest = input;
7668
7669        let parameters = PointerEncodingParameters {
7670            bases: &SectionBaseAddresses::default(),
7671            func_base: None,
7672            address_size: 4,
7673            section: &input,
7674        };
7675        assert_eq!(
7676            parse_encoded_pointer(encoding, ¶meters, &mut rest),
7677            Ok(Pointer::Direct(0x1234))
7678        );
7679        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7680    }
7681
7682    #[test]
7683    fn test_parse_encoded_pointer_udata4() {
7684        let encoding = constants::DW_EH_PE_absptr | constants::DW_EH_PE_udata4;
7685        let expected_rest = [1, 2, 3, 4];
7686
7687        let input = Section::with_endian(Endian::Little)
7688            .L32(0x1234_5678)
7689            .append_bytes(&expected_rest);
7690        let input = input.get_contents().unwrap();
7691        let input = EndianSlice::new(&input, LittleEndian);
7692        let mut rest = input;
7693
7694        let parameters = PointerEncodingParameters {
7695            bases: &SectionBaseAddresses::default(),
7696            func_base: None,
7697            address_size: 4,
7698            section: &input,
7699        };
7700        assert_eq!(
7701            parse_encoded_pointer(encoding, ¶meters, &mut rest),
7702            Ok(Pointer::Direct(0x1234_5678))
7703        );
7704        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7705    }
7706
7707    #[test]
7708    fn test_parse_encoded_pointer_udata8() {
7709        let encoding = constants::DW_EH_PE_absptr | constants::DW_EH_PE_udata8;
7710        let expected_rest = [1, 2, 3, 4];
7711
7712        let input = Section::with_endian(Endian::Little)
7713            .L64(0x1234_5678_1234_5678)
7714            .append_bytes(&expected_rest);
7715        let input = input.get_contents().unwrap();
7716        let input = EndianSlice::new(&input, LittleEndian);
7717        let mut rest = input;
7718
7719        let parameters = PointerEncodingParameters {
7720            bases: &SectionBaseAddresses::default(),
7721            func_base: None,
7722            address_size: 8,
7723            section: &input,
7724        };
7725        assert_eq!(
7726            parse_encoded_pointer(encoding, ¶meters, &mut rest),
7727            Ok(Pointer::Direct(0x1234_5678_1234_5678))
7728        );
7729        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7730    }
7731
7732    #[test]
7733    fn test_parse_encoded_pointer_sleb128() {
7734        let encoding = constants::DW_EH_PE_textrel | constants::DW_EH_PE_sleb128;
7735        let expected_rest = [1, 2, 3, 4];
7736
7737        let input = Section::with_endian(Endian::Little)
7738            .sleb(-0x1111)
7739            .append_bytes(&expected_rest);
7740        let input = input.get_contents().unwrap();
7741        let input = EndianSlice::new(&input, LittleEndian);
7742        let mut rest = input;
7743
7744        let parameters = PointerEncodingParameters {
7745            bases: &BaseAddresses::default().set_text(0x1111_1111).eh_frame,
7746            func_base: None,
7747            address_size: 4,
7748            section: &input,
7749        };
7750        assert_eq!(
7751            parse_encoded_pointer(encoding, ¶meters, &mut rest),
7752            Ok(Pointer::Direct(0x1111_0000))
7753        );
7754        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7755    }
7756
7757    #[test]
7758    fn test_parse_encoded_pointer_sdata2() {
7759        let encoding = constants::DW_EH_PE_absptr | constants::DW_EH_PE_sdata2;
7760        let expected_rest = [1, 2, 3, 4];
7761        let expected = 0x111_i16;
7762
7763        let input = Section::with_endian(Endian::Little)
7764            .L16(expected as u16)
7765            .append_bytes(&expected_rest);
7766        let input = input.get_contents().unwrap();
7767        let input = EndianSlice::new(&input, LittleEndian);
7768        let mut rest = input;
7769
7770        let parameters = PointerEncodingParameters {
7771            bases: &SectionBaseAddresses::default(),
7772            func_base: None,
7773            address_size: 4,
7774            section: &input,
7775        };
7776        assert_eq!(
7777            parse_encoded_pointer(encoding, ¶meters, &mut rest),
7778            Ok(Pointer::Direct(expected as u64))
7779        );
7780        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7781    }
7782
7783    #[test]
7784    fn test_parse_encoded_pointer_sdata4() {
7785        let encoding = constants::DW_EH_PE_absptr | constants::DW_EH_PE_sdata4;
7786        let expected_rest = [1, 2, 3, 4];
7787        let expected = 0x111_1111_i32;
7788
7789        let input = Section::with_endian(Endian::Little)
7790            .L32(expected as u32)
7791            .append_bytes(&expected_rest);
7792        let input = input.get_contents().unwrap();
7793        let input = EndianSlice::new(&input, LittleEndian);
7794        let mut rest = input;
7795
7796        let parameters = PointerEncodingParameters {
7797            bases: &SectionBaseAddresses::default(),
7798            func_base: None,
7799            address_size: 4,
7800            section: &input,
7801        };
7802        assert_eq!(
7803            parse_encoded_pointer(encoding, ¶meters, &mut rest),
7804            Ok(Pointer::Direct(expected as u64))
7805        );
7806        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7807    }
7808
7809    #[test]
7810    fn test_parse_encoded_pointer_sdata8() {
7811        let encoding = constants::DW_EH_PE_absptr | constants::DW_EH_PE_sdata8;
7812        let expected_rest = [1, 2, 3, 4];
7813        let expected = -0x11_1111_1222_2222_i64;
7814
7815        let input = Section::with_endian(Endian::Little)
7816            .L64(expected as u64)
7817            .append_bytes(&expected_rest);
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: 8,
7826            section: &input,
7827        };
7828        assert_eq!(
7829            parse_encoded_pointer(encoding, ¶meters, &mut rest),
7830            Ok(Pointer::Direct(expected as u64))
7831        );
7832        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7833    }
7834
7835    #[test]
7836    fn test_parse_encoded_pointer_omit() {
7837        let encoding = constants::DW_EH_PE_omit;
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, ¶meters, &mut rest),
7852            Err(Error::CannotParseOmitPointerEncoding)
7853        );
7854        assert_eq!(rest, input);
7855    }
7856
7857    #[test]
7858    fn test_parse_encoded_pointer_bad_encoding() {
7859        let encoding = constants::DwEhPe(constants::DW_EH_PE_sdata8.0 + 1);
7860
7861        let input = Section::with_endian(Endian::Little).L32(0x1);
7862        let input = input.get_contents().unwrap();
7863        let input = EndianSlice::new(&input, LittleEndian);
7864        let mut rest = input;
7865
7866        let parameters = PointerEncodingParameters {
7867            bases: &SectionBaseAddresses::default(),
7868            func_base: None,
7869            address_size: 4,
7870            section: &input,
7871        };
7872        assert_eq!(
7873            parse_encoded_pointer(encoding, ¶meters, &mut rest),
7874            Err(Error::UnknownPointerEncoding(encoding))
7875        );
7876    }
7877
7878    #[test]
7879    fn test_parse_encoded_pointer_aligned() {
7880        let encoding = constants::DW_EH_PE_aligned;
7883
7884        let input = Section::with_endian(Endian::Little).L32(0x1);
7885        let input = input.get_contents().unwrap();
7886        let input = EndianSlice::new(&input, LittleEndian);
7887        let mut rest = input;
7888
7889        let parameters = PointerEncodingParameters {
7890            bases: &SectionBaseAddresses::default(),
7891            func_base: None,
7892            address_size: 4,
7893            section: &input,
7894        };
7895        assert_eq!(
7896            parse_encoded_pointer(encoding, ¶meters, &mut rest),
7897            Err(Error::UnsupportedPointerEncoding)
7898        );
7899    }
7900
7901    #[test]
7902    fn test_parse_encoded_pointer_indirect() {
7903        let expected_rest = [1, 2, 3, 4];
7904        let encoding = constants::DW_EH_PE_indirect;
7905
7906        let input = Section::with_endian(Endian::Little)
7907            .L32(0x1234_5678)
7908            .append_bytes(&expected_rest);
7909        let input = input.get_contents().unwrap();
7910        let input = EndianSlice::new(&input, LittleEndian);
7911        let mut rest = input;
7912
7913        let parameters = PointerEncodingParameters {
7914            bases: &SectionBaseAddresses::default(),
7915            func_base: None,
7916            address_size: 4,
7917            section: &input,
7918        };
7919        assert_eq!(
7920            parse_encoded_pointer(encoding, ¶meters, &mut rest),
7921            Ok(Pointer::Indirect(0x1234_5678))
7922        );
7923        assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7924    }
7925
7926    #[test]
7927    fn test_unwind_context_reuse() {
7928        fn unwind_one(ctx: &mut UnwindContext<usize>, data: &[u8]) {
7929            let debug_frame = DebugFrame::new(data, NativeEndian);
7930            let bases = Default::default();
7931            let result = debug_frame.unwind_info_for_address(
7932                &bases,
7933                ctx,
7934                0xbadb_ad99,
7935                DebugFrame::cie_from_offset,
7936            );
7937            assert!(result.is_err());
7938            assert_eq!(result.unwrap_err(), Error::NoUnwindInfoForAddress);
7939        }
7940
7941        let mut ctx: UnwindContext<usize> = UnwindContext::new();
7943        {
7944            let data1 = vec![];
7945            unwind_one(&mut ctx, &data1);
7946        }
7947        {
7948            let data2 = vec![];
7949            unwind_one(&mut ctx, &data2);
7950        }
7951    }
7952}