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