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