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<F>( &self, frame: &EhFrame<R>, bases: &BaseAddresses, ctx: &mut UninitializedUnwindContext<R>, address: u64, get_cie: F, ) -> Result<UnwindTableRow<R>> where F: FnMut( &EhFrame<R>, &BaseAddresses, EhFrameOffset<R::Offset>, ) -> Result<CommonInformationEntry<R>>,372     pub fn unwind_info_for_address<F>(
373         &self,
374         frame: &EhFrame<R>,
375         bases: &BaseAddresses,
376         ctx: &mut UninitializedUnwindContext<R>,
377         address: u64,
378         get_cie: F,
379     ) -> Result<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<F>( &self, bases: &BaseAddresses, ctx: &mut UninitializedUnwindContext<R>, address: u64, get_cie: F, ) -> Result<UnwindTableRow<R>> where F: FnMut(&Self, &BaseAddresses, Self::Offset) -> Result<CommonInformationEntry<R>>,679     fn unwind_info_for_address<F>(
680         &self,
681         bases: &BaseAddresses,
682         ctx: &mut UninitializedUnwindContext<R>,
683         address: u64,
684         get_cie: F,
685     ) -> Result<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, Section: UnwindSection<R>>( &self, section: &'a Section, bases: &'a BaseAddresses, ctx: &'a mut UninitializedUnwindContext<R>, ) -> Result<UnwindTable<'a, R>>1610     pub fn rows<'a, Section: UnwindSection<R>>(
1611         &self,
1612         section: &'a Section,
1613         bases: &'a BaseAddresses,
1614         ctx: &'a mut UninitializedUnwindContext<R>,
1615     ) -> Result<UnwindTable<'a, 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<Section: UnwindSection<R>>( &self, section: &Section, bases: &BaseAddresses, ctx: &mut UninitializedUnwindContext<R>, address: u64, ) -> Result<UnwindTableRow<R>>1625     pub fn unwind_info_for_address<Section: UnwindSection<R>>(
1626         &self,
1627         section: &Section,
1628         bases: &BaseAddresses,
1629         ctx: &mut UninitializedUnwindContext<R>,
1630         address: u64,
1631     ) -> Result<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(row.clone());
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, 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     instructions: CallFrameInstructionIter<'a, R>,
2017     ctx: &'a mut UnwindContext<R>,
2018 }
2019 
2020 /// # Signal Safe Methods
2021 ///
2022 /// These methods are guaranteed not to allocate, acquire locks, or perform any
2023 /// other signal-unsafe operations.
2024 impl<'a, R: Reader> UnwindTable<'a, R> {
2025     /// Construct a new `UnwindTable` for the given
2026     /// `FrameDescriptionEntry`'s CFI unwinding program.
new<Section: UnwindSection<R>>( section: &'a Section, bases: &'a BaseAddresses, ctx: &'a mut UninitializedUnwindContext<R>, fde: &FrameDescriptionEntry<R>, ) -> Result<UnwindTable<'a, R>>2027     pub fn new<Section: UnwindSection<R>>(
2028         section: &'a Section,
2029         bases: &'a BaseAddresses,
2030         ctx: &'a mut UninitializedUnwindContext<R>,
2031         fde: &FrameDescriptionEntry<R>,
2032     ) -> Result<UnwindTable<'a, R>> {
2033         let ctx = ctx.initialize(section, bases, fde.cie())?;
2034         Ok(Self::new_for_fde(section, bases, ctx, fde))
2035     }
2036 
new_for_fde<Section: UnwindSection<R>>( section: &'a Section, bases: &'a BaseAddresses, ctx: &'a mut UnwindContext<R>, fde: &FrameDescriptionEntry<R>, ) -> UnwindTable<'a, R>2037     fn new_for_fde<Section: UnwindSection<R>>(
2038         section: &'a Section,
2039         bases: &'a BaseAddresses,
2040         ctx: &'a mut UnwindContext<R>,
2041         fde: &FrameDescriptionEntry<R>,
2042     ) -> UnwindTable<'a, R> {
2043         assert!(ctx.stack().len() >= 1);
2044         UnwindTable {
2045             code_alignment_factor: Wrapping(fde.cie().code_alignment_factor()),
2046             data_alignment_factor: Wrapping(fde.cie().data_alignment_factor()),
2047             next_start_address: fde.initial_address(),
2048             last_end_address: fde.initial_address().wrapping_add(fde.len()),
2049             returned_last_row: false,
2050             instructions: fde.instructions(section, bases),
2051             ctx,
2052         }
2053     }
2054 
new_for_cie<Section: UnwindSection<R>>( section: &'a Section, bases: &'a BaseAddresses, ctx: &'a mut UnwindContext<R>, cie: &CommonInformationEntry<R>, ) -> UnwindTable<'a, R>2055     fn new_for_cie<Section: UnwindSection<R>>(
2056         section: &'a Section,
2057         bases: &'a BaseAddresses,
2058         ctx: &'a mut UnwindContext<R>,
2059         cie: &CommonInformationEntry<R>,
2060     ) -> UnwindTable<'a, R> {
2061         assert!(ctx.stack().len() >= 1);
2062         UnwindTable {
2063             code_alignment_factor: Wrapping(cie.code_alignment_factor()),
2064             data_alignment_factor: Wrapping(cie.data_alignment_factor()),
2065             next_start_address: 0,
2066             last_end_address: 0,
2067             returned_last_row: false,
2068             instructions: cie.instructions(section, bases),
2069             ctx,
2070         }
2071     }
2072 
2073     /// Evaluate call frame instructions until the next row of the table is
2074     /// completed, and return it.
2075     ///
2076     /// Unfortunately, this cannot be used with `FallibleIterator` because of
2077     /// the restricted lifetime of the yielded item.
next_row(&mut self) -> Result<Option<&UnwindTableRow<R>>>2078     pub fn next_row(&mut self) -> Result<Option<&UnwindTableRow<R>>> {
2079         assert!(self.ctx.stack().len() >= 1);
2080         self.ctx.set_start_address(self.next_start_address);
2081 
2082         loop {
2083             match self.instructions.next() {
2084                 Err(e) => return Err(e),
2085 
2086                 Ok(None) => {
2087                     if self.returned_last_row {
2088                         return Ok(None);
2089                     }
2090 
2091                     let row = self.ctx.row_mut();
2092                     row.end_address = self.last_end_address;
2093 
2094                     self.returned_last_row = true;
2095                     return Ok(Some(row));
2096                 }
2097 
2098                 Ok(Some(instruction)) => {
2099                     if self.evaluate(instruction)? {
2100                         return Ok(Some(self.ctx.row()));
2101                     }
2102                 }
2103             };
2104         }
2105     }
2106 
2107     /// Evaluate one call frame instruction. Return `Ok(true)` if the row is
2108     /// complete, `Ok(false)` otherwise.
evaluate(&mut self, instruction: CallFrameInstruction<R>) -> Result<bool>2109     fn evaluate(&mut self, instruction: CallFrameInstruction<R>) -> Result<bool> {
2110         use crate::CallFrameInstruction::*;
2111 
2112         match instruction {
2113             // Instructions that complete the current row and advance the
2114             // address for the next row.
2115             SetLoc { address } => {
2116                 if address < self.ctx.start_address() {
2117                     return Err(Error::InvalidAddressRange);
2118                 }
2119 
2120                 self.next_start_address = address;
2121                 self.ctx.row_mut().end_address = self.next_start_address;
2122                 return Ok(true);
2123             }
2124             AdvanceLoc { delta } => {
2125                 let delta = Wrapping(u64::from(delta)) * self.code_alignment_factor;
2126                 self.next_start_address = (Wrapping(self.ctx.start_address()) + delta).0;
2127                 self.ctx.row_mut().end_address = self.next_start_address;
2128                 return Ok(true);
2129             }
2130 
2131             // Instructions that modify the CFA.
2132             DefCfa { register, offset } => {
2133                 self.ctx.set_cfa(CfaRule::RegisterAndOffset {
2134                     register,
2135                     offset: offset as i64,
2136                 });
2137             }
2138             DefCfaSf {
2139                 register,
2140                 factored_offset,
2141             } => {
2142                 let data_align = self.data_alignment_factor;
2143                 self.ctx.set_cfa(CfaRule::RegisterAndOffset {
2144                     register,
2145                     offset: (Wrapping(factored_offset) * data_align).0,
2146                 });
2147             }
2148             DefCfaRegister { register } => {
2149                 if let CfaRule::RegisterAndOffset {
2150                     register: ref mut reg,
2151                     ..
2152                 } = *self.ctx.cfa_mut()
2153                 {
2154                     *reg = register;
2155                 } else {
2156                     return Err(Error::CfiInstructionInInvalidContext);
2157                 }
2158             }
2159             DefCfaOffset { offset } => {
2160                 if let CfaRule::RegisterAndOffset {
2161                     offset: ref mut off,
2162                     ..
2163                 } = *self.ctx.cfa_mut()
2164                 {
2165                     *off = offset as i64;
2166                 } else {
2167                     return Err(Error::CfiInstructionInInvalidContext);
2168                 }
2169             }
2170             DefCfaOffsetSf { factored_offset } => {
2171                 if let CfaRule::RegisterAndOffset {
2172                     offset: ref mut off,
2173                     ..
2174                 } = *self.ctx.cfa_mut()
2175                 {
2176                     let data_align = self.data_alignment_factor;
2177                     *off = (Wrapping(factored_offset) * data_align).0;
2178                 } else {
2179                     return Err(Error::CfiInstructionInInvalidContext);
2180                 }
2181             }
2182             DefCfaExpression { expression } => {
2183                 self.ctx.set_cfa(CfaRule::Expression(expression));
2184             }
2185 
2186             // Instructions that define register rules.
2187             Undefined { register } => {
2188                 self.ctx
2189                     .set_register_rule(register, RegisterRule::Undefined)?;
2190             }
2191             SameValue { register } => {
2192                 self.ctx
2193                     .set_register_rule(register, RegisterRule::SameValue)?;
2194             }
2195             Offset {
2196                 register,
2197                 factored_offset,
2198             } => {
2199                 let offset = Wrapping(factored_offset as i64) * self.data_alignment_factor;
2200                 self.ctx
2201                     .set_register_rule(register, RegisterRule::Offset(offset.0))?;
2202             }
2203             OffsetExtendedSf {
2204                 register,
2205                 factored_offset,
2206             } => {
2207                 let offset = Wrapping(factored_offset) * self.data_alignment_factor;
2208                 self.ctx
2209                     .set_register_rule(register, RegisterRule::Offset(offset.0))?;
2210             }
2211             ValOffset {
2212                 register,
2213                 factored_offset,
2214             } => {
2215                 let offset = Wrapping(factored_offset as i64) * self.data_alignment_factor;
2216                 self.ctx
2217                     .set_register_rule(register, RegisterRule::ValOffset(offset.0))?;
2218             }
2219             ValOffsetSf {
2220                 register,
2221                 factored_offset,
2222             } => {
2223                 let offset = Wrapping(factored_offset) * self.data_alignment_factor;
2224                 self.ctx
2225                     .set_register_rule(register, RegisterRule::ValOffset(offset.0))?;
2226             }
2227             Register {
2228                 dest_register,
2229                 src_register,
2230             } => {
2231                 self.ctx
2232                     .set_register_rule(dest_register, RegisterRule::Register(src_register))?;
2233             }
2234             Expression {
2235                 register,
2236                 expression,
2237             } => {
2238                 let expression = RegisterRule::Expression(expression);
2239                 self.ctx.set_register_rule(register, expression)?;
2240             }
2241             ValExpression {
2242                 register,
2243                 expression,
2244             } => {
2245                 let expression = RegisterRule::ValExpression(expression);
2246                 self.ctx.set_register_rule(register, expression)?;
2247             }
2248             Restore { register } => {
2249                 let initial_rule = if let Some(rule) = self.ctx.get_initial_rule(register) {
2250                     rule
2251                 } else {
2252                     // Can't restore the initial rule when we are
2253                     // evaluating the initial rules!
2254                     return Err(Error::CfiInstructionInInvalidContext);
2255                 };
2256 
2257                 self.ctx.set_register_rule(register, initial_rule)?;
2258             }
2259 
2260             // Row push and pop instructions.
2261             RememberState => {
2262                 self.ctx.push_row()?;
2263             }
2264             RestoreState => {
2265                 assert!(self.ctx.stack().len() > 0);
2266                 if self.ctx.stack().len() == 1 {
2267                     return Err(Error::PopWithEmptyStack);
2268                 }
2269                 // Pop state while preserving current location.
2270                 let start_address = self.ctx.start_address();
2271                 self.ctx.pop_row();
2272                 self.ctx.set_start_address(start_address);
2273             }
2274 
2275             // GNU Extension. Save the size somewhere so the unwinder can use
2276             // it when restoring IP
2277             ArgsSize { size } => {
2278                 self.ctx.row_mut().saved_args_size = size;
2279             }
2280 
2281             // No operation.
2282             Nop => {}
2283         };
2284 
2285         Ok(false)
2286     }
2287 }
2288 
2289 // We tend to have very few register rules: usually only a couple. Even if we
2290 // have a rule for every register, on x86-64 with SSE and everything we're
2291 // talking about ~100 rules. So rather than keeping the rules in a hash map, or
2292 // a vector indexed by register number (which would lead to filling lots of
2293 // empty entries), we store them as a vec of (register number, register rule)
2294 // pairs.
2295 //
2296 // Additionally, because every register's default rule is implicitly
2297 // `RegisterRule::Undefined`, we never store a register's rule in this vec if it
2298 // is undefined and save a little bit more space and do a little fewer
2299 // comparisons that way.
2300 //
2301 // The maximum number of rules preallocated by libunwind is 97 for AArch64, 128
2302 // for ARM, and even 188 for MIPS. It is extremely unlikely to encounter this
2303 // many register rules in practice.
2304 //
2305 // See:
2306 // - https://github.com/libunwind/libunwind/blob/11fd461095ea98f4b3e3a361f5a8a558519363fa/include/tdep-x86_64/dwarf-config.h#L36
2307 // - https://github.com/libunwind/libunwind/blob/11fd461095ea98f4b3e3a361f5a8a558519363fa/include/tdep-aarch64/dwarf-config.h#L32
2308 // - https://github.com/libunwind/libunwind/blob/11fd461095ea98f4b3e3a361f5a8a558519363fa/include/tdep-arm/dwarf-config.h#L31
2309 // - https://github.com/libunwind/libunwind/blob/11fd461095ea98f4b3e3a361f5a8a558519363fa/include/tdep-mips/dwarf-config.h#L31
2310 //
2311 // TODO: Consider using const generics for the array size.
2312 struct RegisterRuleMap<R: Reader> {
2313     rules_storage: MaybeUninit<[(Register, RegisterRule<R>); MAX_RULES]>,
2314     rules_len: usize,
2315 }
2316 
2317 const MAX_RULES: usize = 192;
2318 
2319 impl<R: Reader + Debug> Debug for RegisterRuleMap<R> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result2320     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2321         f.debug_struct("RegisterRuleMap")
2322             .field("rules", &self.rules())
2323             .finish()
2324     }
2325 }
2326 
2327 impl<R: Reader> Default for RegisterRuleMap<R> {
default() -> Self2328     fn default() -> Self {
2329         RegisterRuleMap {
2330             rules_storage: MaybeUninit::uninit(),
2331             rules_len: 0,
2332         }
2333     }
2334 }
2335 
2336 impl<R: Reader + Clone> Clone for RegisterRuleMap<R> {
clone(&self) -> Self2337     fn clone(&self) -> Self {
2338         let mut new = RegisterRuleMap::default();
2339         for (register, rule) in self.rules() {
2340             new.push(register.clone(), rule.clone()).unwrap();
2341         }
2342         return new;
2343     }
2344 }
2345 
2346 impl<R: Reader> Drop for RegisterRuleMap<R> {
drop(&mut self)2347     fn drop(&mut self) {
2348         self.clear();
2349     }
2350 }
2351 
2352 /// # Signal Safe Methods
2353 ///
2354 /// These methods are guaranteed not to allocate, acquire locks, or perform any
2355 /// other signal-unsafe operations.
2356 impl<R: Reader> RegisterRuleMap<R> {
is_default(&self) -> bool2357     fn is_default(&self) -> bool {
2358         self.rules_len == 0
2359     }
2360 
rules(&self) -> &[(Register, RegisterRule<R>)]2361     fn rules(&self) -> &[(Register, RegisterRule<R>)] {
2362         // Note that the unsafety here relies on the mutation of
2363         // `self.rules_len` in `self.push` below, which guarantees that once
2364         // we've pushed something the `rules_storage` is valid for that many
2365         // elements.
2366         unsafe {
2367             core::slice::from_raw_parts(self.rules_storage.as_ptr() as *const _, self.rules_len)
2368         }
2369     }
2370 
rules_mut(&mut self) -> &mut [(Register, RegisterRule<R>)]2371     fn rules_mut(&mut self) -> &mut [(Register, RegisterRule<R>)] {
2372         // See the note in `rules` on safety here.
2373         unsafe {
2374             core::slice::from_raw_parts_mut(
2375                 self.rules_storage.as_mut_ptr() as *mut _,
2376                 self.rules_len,
2377             )
2378         }
2379     }
2380 
get(&self, register: Register) -> RegisterRule<R>2381     fn get(&self, register: Register) -> RegisterRule<R> {
2382         self.rules()
2383             .iter()
2384             .find(|rule| rule.0 == register)
2385             .map(|r| {
2386                 debug_assert!(r.1.is_defined());
2387                 r.1.clone()
2388             })
2389             .unwrap_or(RegisterRule::Undefined)
2390     }
2391 
set(&mut self, register: Register, rule: RegisterRule<R>) -> Result<()>2392     fn set(&mut self, register: Register, rule: RegisterRule<R>) -> Result<()> {
2393         if !rule.is_defined() {
2394             let idx = self
2395                 .rules()
2396                 .iter()
2397                 .enumerate()
2398                 .find(|&(_, r)| r.0 == register)
2399                 .map(|(i, _)| i);
2400             if let Some(idx) = idx {
2401                 let (a, b) = self.rules_mut().split_at_mut(idx + 1);
2402                 if b.len() > 0 {
2403                     mem::swap(&mut a[a.len() - 1], &mut b[b.len() - 1]);
2404                 }
2405                 unsafe {
2406                     let ptr = self.rules_storage.as_mut_ptr() as *mut (Register, RegisterRule<R>);
2407                     ptr::drop_in_place(ptr.add(self.rules_len - 1));
2408                     self.rules_len -= 1;
2409                 }
2410             }
2411             return Ok(());
2412         }
2413 
2414         for &mut (reg, ref mut old_rule) in self.rules_mut() {
2415             debug_assert!(old_rule.is_defined());
2416             if reg == register {
2417                 *old_rule = rule;
2418                 return Ok(());
2419             }
2420         }
2421 
2422         self.push(register, rule)
2423     }
2424 
clear(&mut self)2425     fn clear(&mut self) {
2426         unsafe {
2427             ptr::drop_in_place(self.rules_mut());
2428             self.rules_len = 0;
2429         }
2430     }
2431 
iter(&self) -> RegisterRuleIter<R>2432     fn iter(&self) -> RegisterRuleIter<R> {
2433         RegisterRuleIter(self.rules().iter())
2434     }
2435 
push(&mut self, register: Register, rule: RegisterRule<R>) -> Result<()>2436     fn push(&mut self, register: Register, rule: RegisterRule<R>) -> Result<()> {
2437         if self.rules_len >= MAX_RULES {
2438             return Err(Error::TooManyRegisterRules);
2439         }
2440         // The unsafety here comes from working with `MaybeUninit` to initialize
2441         // our 192-element array. We're pushing a new element onto that array
2442         // here. Just above we did a bounds check to make sure we actually have
2443         // space to push something and here we're doing the actual memory write,
2444         // along with an increment of `rules_len` which will affect the unsafe
2445         // implementations of `rules` and `rules_mut` above.
2446         unsafe {
2447             let ptr = self.rules_storage.as_mut_ptr() as *mut (Register, RegisterRule<R>);
2448             ptr::write(ptr.add(self.rules_len), (register, rule));
2449             self.rules_len += 1;
2450         }
2451         Ok(())
2452     }
2453 }
2454 
2455 impl<'a, R> FromIterator<&'a (Register, RegisterRule<R>)> for RegisterRuleMap<R>
2456 where
2457     R: 'a + Reader,
2458 {
from_iter<T>(iter: T) -> RegisterRuleMap<R> where T: IntoIterator<Item = &'a (Register, RegisterRule<R>)>,2459     fn from_iter<T>(iter: T) -> RegisterRuleMap<R>
2460     where
2461         T: IntoIterator<Item = &'a (Register, RegisterRule<R>)>,
2462     {
2463         let iter = iter.into_iter();
2464         let mut rules = RegisterRuleMap::default();
2465         for &(reg, ref rule) in iter.filter(|r| r.1.is_defined()) {
2466             rules.set(reg, rule.clone()).expect(
2467                 "This is only used in tests, impl isn't exposed publicly.
2468                          If you trip this, fix your test",
2469             );
2470         }
2471         rules
2472     }
2473 }
2474 
2475 impl<R> PartialEq for RegisterRuleMap<R>
2476 where
2477     R: Reader + PartialEq,
2478 {
eq(&self, rhs: &Self) -> bool2479     fn eq(&self, rhs: &Self) -> bool {
2480         for &(reg, ref rule) in self.rules() {
2481             debug_assert!(rule.is_defined());
2482             if *rule != rhs.get(reg) {
2483                 return false;
2484             }
2485         }
2486 
2487         for &(reg, ref rhs_rule) in rhs.rules() {
2488             debug_assert!(rhs_rule.is_defined());
2489             if *rhs_rule != self.get(reg) {
2490                 return false;
2491             }
2492         }
2493 
2494         true
2495     }
2496 }
2497 
2498 impl<R> Eq for RegisterRuleMap<R> where R: Reader + Eq {}
2499 
2500 /// An unordered iterator for register rules.
2501 #[derive(Debug, Clone)]
2502 pub struct RegisterRuleIter<'iter, R>(::core::slice::Iter<'iter, (Register, RegisterRule<R>)>)
2503 where
2504     R: Reader;
2505 
2506 impl<'iter, R: Reader> Iterator for RegisterRuleIter<'iter, R> {
2507     type Item = &'iter (Register, RegisterRule<R>);
2508 
next(&mut self) -> Option<Self::Item>2509     fn next(&mut self) -> Option<Self::Item> {
2510         self.0.next()
2511     }
2512 }
2513 
2514 /// A row in the virtual unwind table that describes how to find the values of
2515 /// the registers in the *previous* frame for a range of PC addresses.
2516 #[derive(Clone, Debug, PartialEq, Eq)]
2517 pub struct UnwindTableRow<R: Reader> {
2518     start_address: u64,
2519     end_address: u64,
2520     saved_args_size: u64,
2521     cfa: CfaRule<R>,
2522     registers: RegisterRuleMap<R>,
2523 }
2524 
2525 impl<R: Reader> Default for UnwindTableRow<R> {
default() -> Self2526     fn default() -> Self {
2527         UnwindTableRow {
2528             start_address: 0,
2529             end_address: 0,
2530             saved_args_size: 0,
2531             cfa: Default::default(),
2532             registers: Default::default(),
2533         }
2534     }
2535 }
2536 
2537 impl<R: Reader> UnwindTableRow<R> {
is_default(&self) -> bool2538     fn is_default(&self) -> bool {
2539         self.start_address == 0
2540             && self.end_address == 0
2541             && self.cfa.is_default()
2542             && self.registers.is_default()
2543     }
2544 
2545     /// Get the starting PC address that this row applies to.
start_address(&self) -> u642546     pub fn start_address(&self) -> u64 {
2547         self.start_address
2548     }
2549 
2550     /// Get the end PC address where this row's register rules become
2551     /// unapplicable.
2552     ///
2553     /// In other words, this row describes how to recover the last frame's
2554     /// registers for all PCs where `row.start_address() <= PC <
2555     /// row.end_address()`. This row does NOT describe how to recover registers
2556     /// when `PC == row.end_address()`.
end_address(&self) -> u642557     pub fn end_address(&self) -> u64 {
2558         self.end_address
2559     }
2560 
2561     /// Return `true` if the given `address` is within this row's address range,
2562     /// `false` otherwise.
contains(&self, address: u64) -> bool2563     pub fn contains(&self, address: u64) -> bool {
2564         self.start_address <= address && address < self.end_address
2565     }
2566 
2567     /// Returns the amount of args currently on the stack.
2568     ///
2569     /// When unwinding, if the personality function requested a change in IP,
2570     /// the SP needs to be adjusted by saved_args_size.
saved_args_size(&self) -> u642571     pub fn saved_args_size(&self) -> u64 {
2572         self.saved_args_size
2573     }
2574 
2575     /// Get the canonical frame address (CFA) recovery rule for this row.
cfa(&self) -> &CfaRule<R>2576     pub fn cfa(&self) -> &CfaRule<R> {
2577         &self.cfa
2578     }
2579 
2580     /// Get the register recovery rule for the given register number.
2581     ///
2582     /// The register number mapping is architecture dependent. For example, in
2583     /// the x86-64 ABI the register number mapping is defined in Figure 3.36:
2584     ///
2585     /// > Figure 3.36: DWARF Register Number Mapping
2586     /// >
2587     /// > <table>
2588     /// >   <tr><th>Register Name</th>                    <th>Number</th>  <th>Abbreviation</th></tr>
2589     /// >   <tr><td>General Purpose Register RAX</td>     <td>0</td>       <td>%rax</td></tr>
2590     /// >   <tr><td>General Purpose Register RDX</td>     <td>1</td>       <td>%rdx</td></tr>
2591     /// >   <tr><td>General Purpose Register RCX</td>     <td>2</td>       <td>%rcx</td></tr>
2592     /// >   <tr><td>General Purpose Register RBX</td>     <td>3</td>       <td>%rbx</td></tr>
2593     /// >   <tr><td>General Purpose Register RSI</td>     <td>4</td>       <td>%rsi</td></tr>
2594     /// >   <tr><td>General Purpose Register RDI</td>     <td>5</td>       <td>%rdi</td></tr>
2595     /// >   <tr><td>General Purpose Register RBP</td>     <td>6</td>       <td>%rbp</td></tr>
2596     /// >   <tr><td>Stack Pointer Register RSP</td>       <td>7</td>       <td>%rsp</td></tr>
2597     /// >   <tr><td>Extended Integer Registers 8-15</td>  <td>8-15</td>    <td>%r8-%r15</td></tr>
2598     /// >   <tr><td>Return Address RA</td>                <td>16</td>      <td></td></tr>
2599     /// >   <tr><td>Vector Registers 0–7</td>             <td>17-24</td>   <td>%xmm0–%xmm7</td></tr>
2600     /// >   <tr><td>Extended Vector Registers 8–15</td>   <td>25-32</td>   <td>%xmm8–%xmm15</td></tr>
2601     /// >   <tr><td>Floating Point Registers 0–7</td>     <td>33-40</td>   <td>%st0–%st7</td></tr>
2602     /// >   <tr><td>MMX Registers 0–7</td>                <td>41-48</td>   <td>%mm0–%mm7</td></tr>
2603     /// >   <tr><td>Flag Register</td>                    <td>49</td>      <td>%rFLAGS</td></tr>
2604     /// >   <tr><td>Segment Register ES</td>              <td>50</td>      <td>%es</td></tr>
2605     /// >   <tr><td>Segment Register CS</td>              <td>51</td>      <td>%cs</td></tr>
2606     /// >   <tr><td>Segment Register SS</td>              <td>52</td>      <td>%ss</td></tr>
2607     /// >   <tr><td>Segment Register DS</td>              <td>53</td>      <td>%ds</td></tr>
2608     /// >   <tr><td>Segment Register FS</td>              <td>54</td>      <td>%fs</td></tr>
2609     /// >   <tr><td>Segment Register GS</td>              <td>55</td>      <td>%gs</td></tr>
2610     /// >   <tr><td>Reserved</td>                         <td>56-57</td>   <td></td></tr>
2611     /// >   <tr><td>FS Base address</td>                  <td>58</td>      <td>%fs.base</td></tr>
2612     /// >   <tr><td>GS Base address</td>                  <td>59</td>      <td>%gs.base</td></tr>
2613     /// >   <tr><td>Reserved</td>                         <td>60-61</td>   <td></td></tr>
2614     /// >   <tr><td>Task Register</td>                    <td>62</td>      <td>%tr</td></tr>
2615     /// >   <tr><td>LDT Register</td>                     <td>63</td>      <td>%ldtr</td></tr>
2616     /// >   <tr><td>128-bit Media Control and Status</td> <td>64</td>      <td>%mxcsr</td></tr>
2617     /// >   <tr><td>x87 Control Word</td>                 <td>65</td>      <td>%fcw</td></tr>
2618     /// >   <tr><td>x87 Status Word</td>                  <td>66</td>      <td>%fsw</td></tr>
2619     /// >   <tr><td>Upper Vector Registers 16–31</td>     <td>67-82</td>   <td>%xmm16–%xmm31</td></tr>
2620     /// >   <tr><td>Reserved</td>                         <td>83-117</td>  <td></td></tr>
2621     /// >   <tr><td>Vector Mask Registers 0–7</td>        <td>118-125</td> <td>%k0–%k7</td></tr>
2622     /// >   <tr><td>Reserved</td>                         <td>126-129</td> <td></td></tr>
2623     /// > </table>
register(&self, register: Register) -> RegisterRule<R>2624     pub fn register(&self, register: Register) -> RegisterRule<R> {
2625         self.registers.get(register)
2626     }
2627 
2628     /// Iterate over all defined register `(number, rule)` pairs.
2629     ///
2630     /// The rules are not iterated in any guaranteed order. Any register that
2631     /// does not make an appearance in the iterator implicitly has the rule
2632     /// `RegisterRule::Undefined`.
2633     ///
2634     /// ```
2635     /// # use gimli::{EndianSlice, LittleEndian, UnwindTableRow};
2636     /// # fn foo<'input>(unwind_table_row: UnwindTableRow<EndianSlice<'input, LittleEndian>>) {
2637     /// for &(register, ref rule) in unwind_table_row.registers() {
2638     ///     // ...
2639     ///     # drop(register); drop(rule);
2640     /// }
2641     /// # }
2642     /// ```
registers(&self) -> RegisterRuleIter<R>2643     pub fn registers(&self) -> RegisterRuleIter<R> {
2644         self.registers.iter()
2645     }
2646 }
2647 
2648 /// The canonical frame address (CFA) recovery rules.
2649 #[derive(Clone, Debug, PartialEq, Eq)]
2650 pub enum CfaRule<R: Reader> {
2651     /// The CFA is given offset from the given register's value.
2652     RegisterAndOffset {
2653         /// The register containing the base value.
2654         register: Register,
2655         /// The offset from the register's base value.
2656         offset: i64,
2657     },
2658     /// The CFA is obtained by evaluating this `Reader` as a DWARF expression
2659     /// program.
2660     Expression(Expression<R>),
2661 }
2662 
2663 impl<R: Reader> Default for CfaRule<R> {
default() -> Self2664     fn default() -> Self {
2665         CfaRule::RegisterAndOffset {
2666             register: Register(0),
2667             offset: 0,
2668         }
2669     }
2670 }
2671 
2672 impl<R: Reader> CfaRule<R> {
is_default(&self) -> bool2673     fn is_default(&self) -> bool {
2674         match *self {
2675             CfaRule::RegisterAndOffset { register, offset } => {
2676                 register == Register(0) && offset == 0
2677             }
2678             _ => false,
2679         }
2680     }
2681 }
2682 
2683 /// An entry in the abstract CFI table that describes how to find the value of a
2684 /// register.
2685 ///
2686 /// "The register columns contain rules that describe whether a given register
2687 /// has been saved and the rule to find the value for the register in the
2688 /// previous frame."
2689 #[derive(Clone, Debug, PartialEq, Eq)]
2690 pub enum RegisterRule<R: Reader> {
2691     /// > A register that has this rule has no recoverable value in the previous
2692     /// > frame. (By convention, it is not preserved by a callee.)
2693     Undefined,
2694 
2695     /// > This register has not been modified from the previous frame. (By
2696     /// > convention, it is preserved by the callee, but the callee has not
2697     /// > modified it.)
2698     SameValue,
2699 
2700     /// "The previous value of this register is saved at the address CFA+N where
2701     /// CFA is the current CFA value and N is a signed offset."
2702     Offset(i64),
2703 
2704     /// "The previous value of this register is the value CFA+N where CFA is the
2705     /// current CFA value and N is a signed offset."
2706     ValOffset(i64),
2707 
2708     /// "The previous value of this register is stored in another register
2709     /// numbered R."
2710     Register(Register),
2711 
2712     /// "The previous value of this register is located at the address produced
2713     /// by executing the DWARF expression."
2714     Expression(Expression<R>),
2715 
2716     /// "The previous value of this register is the value produced by executing
2717     /// the DWARF expression."
2718     ValExpression(Expression<R>),
2719 
2720     /// "The rule is defined externally to this specification by the augmenter."
2721     Architectural,
2722 }
2723 
2724 impl<R: Reader> RegisterRule<R> {
is_defined(&self) -> bool2725     fn is_defined(&self) -> bool {
2726         match *self {
2727             RegisterRule::Undefined => false,
2728             _ => true,
2729         }
2730     }
2731 }
2732 
2733 /// A parsed call frame instruction.
2734 #[derive(Clone, Debug, PartialEq, Eq)]
2735 pub enum CallFrameInstruction<R: Reader> {
2736     // 6.4.2.1 Row Creation Methods
2737     /// > 1. DW_CFA_set_loc
2738     /// >
2739     /// > The DW_CFA_set_loc instruction takes a single operand that represents
2740     /// > a target address. The required action is to create a new table row
2741     /// > using the specified address as the location. All other values in the
2742     /// > new row are initially identical to the current row. The new location
2743     /// > value is always greater than the current one. If the segment_size
2744     /// > field of this FDE's CIE is non- zero, the initial location is preceded
2745     /// > by a segment selector of the given length.
2746     SetLoc {
2747         /// The target address.
2748         address: u64,
2749     },
2750 
2751     /// The `AdvanceLoc` instruction is used for all of `DW_CFA_advance_loc` and
2752     /// `DW_CFA_advance_loc{1,2,4}`.
2753     ///
2754     /// > 2. DW_CFA_advance_loc
2755     /// >
2756     /// > The DW_CFA_advance instruction takes a single operand (encoded with
2757     /// > the opcode) that represents a constant delta. The required action is
2758     /// > to create a new table row with a location value that is computed by
2759     /// > taking the current entry’s location value and adding the value of
2760     /// > delta * code_alignment_factor. All other values in the new row are
2761     /// > initially identical to the current row.
2762     AdvanceLoc {
2763         /// The delta to be added to the current address.
2764         delta: u32,
2765     },
2766 
2767     // 6.4.2.2 CFA Definition Methods
2768     /// > 1. DW_CFA_def_cfa
2769     /// >
2770     /// > The DW_CFA_def_cfa instruction takes two unsigned LEB128 operands
2771     /// > representing a register number and a (non-factored) offset. The
2772     /// > required action is to define the current CFA rule to use the provided
2773     /// > register and offset.
2774     DefCfa {
2775         /// The target register's number.
2776         register: Register,
2777         /// The non-factored offset.
2778         offset: u64,
2779     },
2780 
2781     /// > 2. DW_CFA_def_cfa_sf
2782     /// >
2783     /// > The DW_CFA_def_cfa_sf instruction takes two operands: an unsigned
2784     /// > LEB128 value representing a register number and a signed LEB128
2785     /// > factored offset. This instruction is identical to DW_CFA_def_cfa
2786     /// > except that the second operand is signed and factored. The resulting
2787     /// > offset is factored_offset * data_alignment_factor.
2788     DefCfaSf {
2789         /// The target register's number.
2790         register: Register,
2791         /// The factored offset.
2792         factored_offset: i64,
2793     },
2794 
2795     /// > 3. DW_CFA_def_cfa_register
2796     /// >
2797     /// > The DW_CFA_def_cfa_register instruction takes a single unsigned LEB128
2798     /// > operand representing a register number. The required action is to
2799     /// > define the current CFA rule to use the provided register (but to keep
2800     /// > the old offset). This operation is valid only if the current CFA rule
2801     /// > is defined to use a register and offset.
2802     DefCfaRegister {
2803         /// The target register's number.
2804         register: Register,
2805     },
2806 
2807     /// > 4. DW_CFA_def_cfa_offset
2808     /// >
2809     /// > The DW_CFA_def_cfa_offset instruction takes a single unsigned LEB128
2810     /// > operand representing a (non-factored) offset. The required action is
2811     /// > to define the current CFA rule to use the provided offset (but to keep
2812     /// > the old register). This operation is valid only if the current CFA
2813     /// > rule is defined to use a register and offset.
2814     DefCfaOffset {
2815         /// The non-factored offset.
2816         offset: u64,
2817     },
2818 
2819     /// > 5. DW_CFA_def_cfa_offset_sf
2820     /// >
2821     /// > The DW_CFA_def_cfa_offset_sf instruction takes a signed LEB128 operand
2822     /// > representing a factored offset. This instruction is identical to
2823     /// > DW_CFA_def_cfa_offset except that the operand is signed and
2824     /// > factored. The resulting offset is factored_offset *
2825     /// > data_alignment_factor. This operation is valid only if the current CFA
2826     /// > rule is defined to use a register and offset.
2827     DefCfaOffsetSf {
2828         /// The factored offset.
2829         factored_offset: i64,
2830     },
2831 
2832     /// > 6. DW_CFA_def_cfa_expression
2833     /// >
2834     /// > The DW_CFA_def_cfa_expression instruction takes a single operand
2835     /// > encoded as a DW_FORM_exprloc value representing a DWARF
2836     /// > expression. The required action is to establish that expression as the
2837     /// > means by which the current CFA is computed.
2838     DefCfaExpression {
2839         /// The DWARF expression.
2840         expression: Expression<R>,
2841     },
2842 
2843     // 6.4.2.3 Register Rule Instructions
2844     /// > 1. DW_CFA_undefined
2845     /// >
2846     /// > The DW_CFA_undefined instruction takes a single unsigned LEB128
2847     /// > operand that represents a register number. The required action is to
2848     /// > set the rule for the specified register to “undefined.”
2849     Undefined {
2850         /// The target register's number.
2851         register: Register,
2852     },
2853 
2854     /// > 2. DW_CFA_same_value
2855     /// >
2856     /// > The DW_CFA_same_value instruction takes a single unsigned LEB128
2857     /// > operand that represents a register number. The required action is to
2858     /// > set the rule for the specified register to “same value.”
2859     SameValue {
2860         /// The target register's number.
2861         register: Register,
2862     },
2863 
2864     /// The `Offset` instruction represents both `DW_CFA_offset` and
2865     /// `DW_CFA_offset_extended`.
2866     ///
2867     /// > 3. DW_CFA_offset
2868     /// >
2869     /// > The DW_CFA_offset instruction takes two operands: a register number
2870     /// > (encoded with the opcode) and an unsigned LEB128 constant representing
2871     /// > a factored offset. The required action is to change the rule for the
2872     /// > register indicated by the register number to be an offset(N) rule
2873     /// > where the value of N is factored offset * data_alignment_factor.
2874     Offset {
2875         /// The target register's number.
2876         register: Register,
2877         /// The factored offset.
2878         factored_offset: u64,
2879     },
2880 
2881     /// > 5. DW_CFA_offset_extended_sf
2882     /// >
2883     /// > The DW_CFA_offset_extended_sf instruction takes two operands: an
2884     /// > unsigned LEB128 value representing a register number and a signed
2885     /// > LEB128 factored offset. This instruction is identical to
2886     /// > DW_CFA_offset_extended except that the second operand is signed and
2887     /// > factored. The resulting offset is factored_offset *
2888     /// > data_alignment_factor.
2889     OffsetExtendedSf {
2890         /// The target register's number.
2891         register: Register,
2892         /// The factored offset.
2893         factored_offset: i64,
2894     },
2895 
2896     /// > 6. DW_CFA_val_offset
2897     /// >
2898     /// > The DW_CFA_val_offset instruction takes two unsigned LEB128 operands
2899     /// > representing a register number and a factored offset. The required
2900     /// > action is to change the rule for the register indicated by the
2901     /// > register number to be a val_offset(N) rule where the value of N is
2902     /// > factored_offset * data_alignment_factor.
2903     ValOffset {
2904         /// The target register's number.
2905         register: Register,
2906         /// The factored offset.
2907         factored_offset: u64,
2908     },
2909 
2910     /// > 7. DW_CFA_val_offset_sf
2911     /// >
2912     /// > The DW_CFA_val_offset_sf instruction takes two operands: an unsigned
2913     /// > LEB128 value representing a register number and a signed LEB128
2914     /// > factored offset. This instruction is identical to DW_CFA_val_offset
2915     /// > except that the second operand is signed and factored. The resulting
2916     /// > offset is factored_offset * data_alignment_factor.
2917     ValOffsetSf {
2918         /// The target register's number.
2919         register: Register,
2920         /// The factored offset.
2921         factored_offset: i64,
2922     },
2923 
2924     /// > 8. DW_CFA_register
2925     /// >
2926     /// > The DW_CFA_register instruction takes two unsigned LEB128 operands
2927     /// > representing register numbers. The required action is to set the rule
2928     /// > for the first register to be register(R) where R is the second
2929     /// > register.
2930     Register {
2931         /// The number of the register whose rule is being changed.
2932         dest_register: Register,
2933         /// The number of the register where the other register's value can be
2934         /// found.
2935         src_register: Register,
2936     },
2937 
2938     /// > 9. DW_CFA_expression
2939     /// >
2940     /// > The DW_CFA_expression instruction takes two operands: an unsigned
2941     /// > LEB128 value representing a register number, and a DW_FORM_block value
2942     /// > representing a DWARF expression. The required action is to change the
2943     /// > rule for the register indicated by the register number to be an
2944     /// > expression(E) rule where E is the DWARF expression. That is, the DWARF
2945     /// > expression computes the address. The value of the CFA is pushed on the
2946     /// > DWARF evaluation stack prior to execution of the DWARF expression.
2947     Expression {
2948         /// The target register's number.
2949         register: Register,
2950         /// The DWARF expression.
2951         expression: Expression<R>,
2952     },
2953 
2954     /// > 10. DW_CFA_val_expression
2955     /// >
2956     /// > The DW_CFA_val_expression instruction takes two operands: an unsigned
2957     /// > LEB128 value representing a register number, and a DW_FORM_block value
2958     /// > representing a DWARF expression. The required action is to change the
2959     /// > rule for the register indicated by the register number to be a
2960     /// > val_expression(E) rule where E is the DWARF expression. That is, the
2961     /// > DWARF expression computes the value of the given register. The value
2962     /// > of the CFA is pushed on the DWARF evaluation stack prior to execution
2963     /// > of the DWARF expression.
2964     ValExpression {
2965         /// The target register's number.
2966         register: Register,
2967         /// The DWARF expression.
2968         expression: Expression<R>,
2969     },
2970 
2971     /// The `Restore` instruction represents both `DW_CFA_restore` and
2972     /// `DW_CFA_restore_extended`.
2973     ///
2974     /// > 11. DW_CFA_restore
2975     /// >
2976     /// > The DW_CFA_restore instruction takes a single operand (encoded with
2977     /// > the opcode) that represents a register number. The required action is
2978     /// > to change the rule for the indicated register to the rule assigned it
2979     /// > by the initial_instructions in the CIE.
2980     Restore {
2981         /// The register to be reset.
2982         register: Register,
2983     },
2984 
2985     // 6.4.2.4 Row State Instructions
2986     /// > 1. DW_CFA_remember_state
2987     /// >
2988     /// > The DW_CFA_remember_state instruction takes no operands. The required
2989     /// > action is to push the set of rules for every register onto an implicit
2990     /// > stack.
2991     RememberState,
2992 
2993     /// > 2. DW_CFA_restore_state
2994     /// >
2995     /// > The DW_CFA_restore_state instruction takes no operands. The required
2996     /// > action is to pop the set of rules off the implicit stack and place
2997     /// > them in the current row.
2998     RestoreState,
2999 
3000     /// > DW_CFA_GNU_args_size
3001     /// >
3002     /// > GNU Extension
3003     /// >
3004     /// > The DW_CFA_GNU_args_size instruction takes an unsigned LEB128 operand
3005     /// > representing an argument size. This instruction specifies the total of
3006     /// > the size of the arguments which have been pushed onto the stack.
3007     ArgsSize {
3008         /// The size of the arguments which have been pushed onto the stack
3009         size: u64,
3010     },
3011 
3012     // 6.4.2.5 Padding Instruction
3013     /// > 1. DW_CFA_nop
3014     /// >
3015     /// > The DW_CFA_nop instruction has no operands and no required actions. It
3016     /// > is used as padding to make a CIE or FDE an appropriate size.
3017     Nop,
3018 }
3019 
3020 const CFI_INSTRUCTION_HIGH_BITS_MASK: u8 = 0b1100_0000;
3021 const CFI_INSTRUCTION_LOW_BITS_MASK: u8 = !CFI_INSTRUCTION_HIGH_BITS_MASK;
3022 
3023 impl<R: Reader> CallFrameInstruction<R> {
parse( input: &mut R, address_encoding: Option<DwEhPe>, parameters: &PointerEncodingParameters<R>, ) -> Result<CallFrameInstruction<R>>3024     fn parse(
3025         input: &mut R,
3026         address_encoding: Option<DwEhPe>,
3027         parameters: &PointerEncodingParameters<R>,
3028     ) -> Result<CallFrameInstruction<R>> {
3029         let instruction = input.read_u8()?;
3030         let high_bits = instruction & CFI_INSTRUCTION_HIGH_BITS_MASK;
3031 
3032         if high_bits == constants::DW_CFA_advance_loc.0 {
3033             let delta = instruction & CFI_INSTRUCTION_LOW_BITS_MASK;
3034             return Ok(CallFrameInstruction::AdvanceLoc {
3035                 delta: u32::from(delta),
3036             });
3037         }
3038 
3039         if high_bits == constants::DW_CFA_offset.0 {
3040             let register = Register((instruction & CFI_INSTRUCTION_LOW_BITS_MASK).into());
3041             let offset = input.read_uleb128()?;
3042             return Ok(CallFrameInstruction::Offset {
3043                 register,
3044                 factored_offset: offset,
3045             });
3046         }
3047 
3048         if high_bits == constants::DW_CFA_restore.0 {
3049             let register = Register((instruction & CFI_INSTRUCTION_LOW_BITS_MASK).into());
3050             return Ok(CallFrameInstruction::Restore { register });
3051         }
3052 
3053         debug_assert_eq!(high_bits, 0);
3054         let instruction = constants::DwCfa(instruction);
3055 
3056         match instruction {
3057             constants::DW_CFA_nop => Ok(CallFrameInstruction::Nop),
3058 
3059             constants::DW_CFA_set_loc => {
3060                 let address = if let Some(encoding) = address_encoding {
3061                     match parse_encoded_pointer(encoding, parameters, input)? {
3062                         Pointer::Direct(x) => x,
3063                         _ => return Err(Error::UnsupportedPointerEncoding),
3064                     }
3065                 } else {
3066                     input.read_address(parameters.address_size)?
3067                 };
3068                 Ok(CallFrameInstruction::SetLoc { address })
3069             }
3070 
3071             constants::DW_CFA_advance_loc1 => {
3072                 let delta = input.read_u8()?;
3073                 Ok(CallFrameInstruction::AdvanceLoc {
3074                     delta: u32::from(delta),
3075                 })
3076             }
3077 
3078             constants::DW_CFA_advance_loc2 => {
3079                 let delta = input.read_u16()?;
3080                 Ok(CallFrameInstruction::AdvanceLoc {
3081                     delta: u32::from(delta),
3082                 })
3083             }
3084 
3085             constants::DW_CFA_advance_loc4 => {
3086                 let delta = input.read_u32()?;
3087                 Ok(CallFrameInstruction::AdvanceLoc { delta })
3088             }
3089 
3090             constants::DW_CFA_offset_extended => {
3091                 let register = input.read_uleb128().and_then(Register::from_u64)?;
3092                 let offset = input.read_uleb128()?;
3093                 Ok(CallFrameInstruction::Offset {
3094                     register,
3095                     factored_offset: offset,
3096                 })
3097             }
3098 
3099             constants::DW_CFA_restore_extended => {
3100                 let register = input.read_uleb128().and_then(Register::from_u64)?;
3101                 Ok(CallFrameInstruction::Restore { register })
3102             }
3103 
3104             constants::DW_CFA_undefined => {
3105                 let register = input.read_uleb128().and_then(Register::from_u64)?;
3106                 Ok(CallFrameInstruction::Undefined { register })
3107             }
3108 
3109             constants::DW_CFA_same_value => {
3110                 let register = input.read_uleb128().and_then(Register::from_u64)?;
3111                 Ok(CallFrameInstruction::SameValue { register })
3112             }
3113 
3114             constants::DW_CFA_register => {
3115                 let dest = input.read_uleb128().and_then(Register::from_u64)?;
3116                 let src = input.read_uleb128().and_then(Register::from_u64)?;
3117                 Ok(CallFrameInstruction::Register {
3118                     dest_register: dest,
3119                     src_register: src,
3120                 })
3121             }
3122 
3123             constants::DW_CFA_remember_state => Ok(CallFrameInstruction::RememberState),
3124 
3125             constants::DW_CFA_restore_state => Ok(CallFrameInstruction::RestoreState),
3126 
3127             constants::DW_CFA_def_cfa => {
3128                 let register = input.read_uleb128().and_then(Register::from_u64)?;
3129                 let offset = input.read_uleb128()?;
3130                 Ok(CallFrameInstruction::DefCfa { register, offset })
3131             }
3132 
3133             constants::DW_CFA_def_cfa_register => {
3134                 let register = input.read_uleb128().and_then(Register::from_u64)?;
3135                 Ok(CallFrameInstruction::DefCfaRegister { register })
3136             }
3137 
3138             constants::DW_CFA_def_cfa_offset => {
3139                 let offset = input.read_uleb128()?;
3140                 Ok(CallFrameInstruction::DefCfaOffset { offset })
3141             }
3142 
3143             constants::DW_CFA_def_cfa_expression => {
3144                 let len = input.read_uleb128().and_then(R::Offset::from_u64)?;
3145                 let expression = input.split(len)?;
3146                 Ok(CallFrameInstruction::DefCfaExpression {
3147                     expression: Expression(expression),
3148                 })
3149             }
3150 
3151             constants::DW_CFA_expression => {
3152                 let register = input.read_uleb128().and_then(Register::from_u64)?;
3153                 let len = input.read_uleb128().and_then(R::Offset::from_u64)?;
3154                 let expression = input.split(len)?;
3155                 Ok(CallFrameInstruction::Expression {
3156                     register,
3157                     expression: Expression(expression),
3158                 })
3159             }
3160 
3161             constants::DW_CFA_offset_extended_sf => {
3162                 let register = input.read_uleb128().and_then(Register::from_u64)?;
3163                 let offset = input.read_sleb128()?;
3164                 Ok(CallFrameInstruction::OffsetExtendedSf {
3165                     register,
3166                     factored_offset: offset,
3167                 })
3168             }
3169 
3170             constants::DW_CFA_def_cfa_sf => {
3171                 let register = input.read_uleb128().and_then(Register::from_u64)?;
3172                 let offset = input.read_sleb128()?;
3173                 Ok(CallFrameInstruction::DefCfaSf {
3174                     register,
3175                     factored_offset: offset,
3176                 })
3177             }
3178 
3179             constants::DW_CFA_def_cfa_offset_sf => {
3180                 let offset = input.read_sleb128()?;
3181                 Ok(CallFrameInstruction::DefCfaOffsetSf {
3182                     factored_offset: offset,
3183                 })
3184             }
3185 
3186             constants::DW_CFA_val_offset => {
3187                 let register = input.read_uleb128().and_then(Register::from_u64)?;
3188                 let offset = input.read_uleb128()?;
3189                 Ok(CallFrameInstruction::ValOffset {
3190                     register,
3191                     factored_offset: offset,
3192                 })
3193             }
3194 
3195             constants::DW_CFA_val_offset_sf => {
3196                 let register = input.read_uleb128().and_then(Register::from_u64)?;
3197                 let offset = input.read_sleb128()?;
3198                 Ok(CallFrameInstruction::ValOffsetSf {
3199                     register,
3200                     factored_offset: offset,
3201                 })
3202             }
3203 
3204             constants::DW_CFA_val_expression => {
3205                 let register = input.read_uleb128().and_then(Register::from_u64)?;
3206                 let len = input.read_uleb128().and_then(R::Offset::from_u64)?;
3207                 let expression = input.split(len)?;
3208                 Ok(CallFrameInstruction::ValExpression {
3209                     register,
3210                     expression: Expression(expression),
3211                 })
3212             }
3213 
3214             constants::DW_CFA_GNU_args_size => {
3215                 let size = input.read_uleb128()?;
3216                 Ok(CallFrameInstruction::ArgsSize { size })
3217             }
3218 
3219             otherwise => Err(Error::UnknownCallFrameInstruction(otherwise)),
3220         }
3221     }
3222 }
3223 
3224 /// A lazy iterator parsing call frame instructions.
3225 ///
3226 /// Can be [used with
3227 /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
3228 #[derive(Clone, Debug)]
3229 pub struct CallFrameInstructionIter<'a, R: Reader> {
3230     input: R,
3231     address_encoding: Option<constants::DwEhPe>,
3232     parameters: PointerEncodingParameters<'a, R>,
3233 }
3234 
3235 impl<'a, R: Reader> CallFrameInstructionIter<'a, R> {
3236     /// Parse the next call frame instruction.
next(&mut self) -> Result<Option<CallFrameInstruction<R>>>3237     pub fn next(&mut self) -> Result<Option<CallFrameInstruction<R>>> {
3238         if self.input.is_empty() {
3239             return Ok(None);
3240         }
3241 
3242         match CallFrameInstruction::parse(&mut self.input, self.address_encoding, &self.parameters)
3243         {
3244             Ok(instruction) => Ok(Some(instruction)),
3245             Err(e) => {
3246                 self.input.empty();
3247                 Err(e)
3248             }
3249         }
3250     }
3251 }
3252 
3253 #[cfg(feature = "fallible-iterator")]
3254 impl<'a, R: Reader> fallible_iterator::FallibleIterator for CallFrameInstructionIter<'a, R> {
3255     type Item = CallFrameInstruction<R>;
3256     type Error = Error;
3257 
next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error>3258     fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
3259         CallFrameInstructionIter::next(self)
3260     }
3261 }
3262 
3263 /// Parse a `DW_EH_PE_*` pointer encoding.
3264 #[doc(hidden)]
3265 #[inline]
parse_pointer_encoding<R: Reader>(input: &mut R) -> Result<constants::DwEhPe>3266 fn parse_pointer_encoding<R: Reader>(input: &mut R) -> Result<constants::DwEhPe> {
3267     let eh_pe = input.read_u8()?;
3268     let eh_pe = constants::DwEhPe(eh_pe);
3269 
3270     if eh_pe.is_valid_encoding() {
3271         Ok(eh_pe)
3272     } else {
3273         Err(Error::UnknownPointerEncoding)
3274     }
3275 }
3276 
3277 /// A decoded pointer.
3278 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
3279 pub enum Pointer {
3280     /// This value is the decoded pointer value.
3281     Direct(u64),
3282 
3283     /// This value is *not* the pointer value, but points to the address of
3284     /// where the real pointer value lives. In other words, deref this pointer
3285     /// to get the real pointer value.
3286     ///
3287     /// Chase this pointer at your own risk: do you trust the DWARF data it came
3288     /// from?
3289     Indirect(u64),
3290 }
3291 
3292 impl Default for Pointer {
3293     #[inline]
default() -> Self3294     fn default() -> Self {
3295         Pointer::Direct(0)
3296     }
3297 }
3298 
3299 impl Into<u64> for Pointer {
3300     #[inline]
into(self) -> u643301     fn into(self) -> u64 {
3302         match self {
3303             Pointer::Direct(p) | Pointer::Indirect(p) => p,
3304         }
3305     }
3306 }
3307 
3308 impl Pointer {
3309     #[inline]
new(encoding: constants::DwEhPe, address: u64) -> Pointer3310     fn new(encoding: constants::DwEhPe, address: u64) -> Pointer {
3311         if encoding.is_indirect() {
3312             Pointer::Indirect(address)
3313         } else {
3314             Pointer::Direct(address)
3315         }
3316     }
3317 }
3318 
3319 #[derive(Clone, Debug)]
3320 struct PointerEncodingParameters<'a, R: Reader> {
3321     bases: &'a SectionBaseAddresses,
3322     func_base: Option<u64>,
3323     address_size: u8,
3324     section: &'a R,
3325 }
3326 
parse_encoded_pointer<R: Reader>( encoding: constants::DwEhPe, parameters: &PointerEncodingParameters<R>, input: &mut R, ) -> Result<Pointer>3327 fn parse_encoded_pointer<R: Reader>(
3328     encoding: constants::DwEhPe,
3329     parameters: &PointerEncodingParameters<R>,
3330     input: &mut R,
3331 ) -> Result<Pointer> {
3332     // TODO: check this once only in parse_pointer_encoding
3333     if !encoding.is_valid_encoding() {
3334         return Err(Error::UnknownPointerEncoding);
3335     }
3336 
3337     if encoding == constants::DW_EH_PE_omit {
3338         return Err(Error::CannotParseOmitPointerEncoding);
3339     }
3340 
3341     let base = match encoding.application() {
3342         constants::DW_EH_PE_absptr => 0,
3343         constants::DW_EH_PE_pcrel => {
3344             if let Some(section_base) = parameters.bases.section {
3345                 let offset_from_section = input.offset_from(parameters.section);
3346                 section_base.wrapping_add(offset_from_section.into_u64())
3347             } else {
3348                 return Err(Error::PcRelativePointerButSectionBaseIsUndefined);
3349             }
3350         }
3351         constants::DW_EH_PE_textrel => {
3352             if let Some(text) = parameters.bases.text {
3353                 text
3354             } else {
3355                 return Err(Error::TextRelativePointerButTextBaseIsUndefined);
3356             }
3357         }
3358         constants::DW_EH_PE_datarel => {
3359             if let Some(data) = parameters.bases.data {
3360                 data
3361             } else {
3362                 return Err(Error::DataRelativePointerButDataBaseIsUndefined);
3363             }
3364         }
3365         constants::DW_EH_PE_funcrel => {
3366             if let Some(func) = parameters.func_base {
3367                 func
3368             } else {
3369                 return Err(Error::FuncRelativePointerInBadContext);
3370             }
3371         }
3372         constants::DW_EH_PE_aligned => return Err(Error::UnsupportedPointerEncoding),
3373         _ => unreachable!(),
3374     };
3375 
3376     let offset = match encoding.format() {
3377         // Unsigned variants.
3378         constants::DW_EH_PE_absptr => input.read_address(parameters.address_size),
3379         constants::DW_EH_PE_uleb128 => input.read_uleb128(),
3380         constants::DW_EH_PE_udata2 => input.read_u16().map(u64::from),
3381         constants::DW_EH_PE_udata4 => input.read_u32().map(u64::from),
3382         constants::DW_EH_PE_udata8 => input.read_u64(),
3383 
3384         // Signed variants. Here we sign extend the values (happens by
3385         // default when casting a signed integer to a larger range integer
3386         // in Rust), return them as u64, and rely on wrapping addition to do
3387         // the right thing when adding these offsets to their bases.
3388         constants::DW_EH_PE_sleb128 => input.read_sleb128().map(|a| a as u64),
3389         constants::DW_EH_PE_sdata2 => input.read_i16().map(|a| a as u64),
3390         constants::DW_EH_PE_sdata4 => input.read_i32().map(|a| a as u64),
3391         constants::DW_EH_PE_sdata8 => input.read_i64().map(|a| a as u64),
3392 
3393         // That was all of the valid encoding formats.
3394         _ => unreachable!(),
3395     }?;
3396 
3397     Ok(Pointer::new(encoding, base.wrapping_add(offset)))
3398 }
3399 
3400 #[cfg(test)]
3401 mod tests {
3402     use super::*;
3403     use super::{parse_cfi_entry, AugmentationData, RegisterRuleMap, UnwindContext};
3404     use crate::common::Format;
3405     use crate::constants;
3406     use crate::endianity::{BigEndian, Endianity, LittleEndian, NativeEndian};
3407     use crate::read::{
3408         EndianSlice, Error, Expression, Pointer, ReaderOffsetId, Result, Section as ReadSection,
3409     };
3410     use crate::test_util::GimliSectionMethods;
3411     use alloc::vec::Vec;
3412     use core::marker::PhantomData;
3413     use core::mem;
3414     use core::u64;
3415     use test_assembler::{Endian, Label, LabelMaker, LabelOrNum, Section, ToLabelOrNum};
3416 
3417     // Ensure each test tries to read the same section kind that it wrote.
3418     #[derive(Clone, Copy)]
3419     struct SectionKind<Section>(PhantomData<Section>);
3420 
3421     impl<T> SectionKind<T> {
endian<'input, E>(self) -> Endian where E: Endianity, T: UnwindSection<EndianSlice<'input, E>>, T::Offset: UnwindOffset<usize>,3422         fn endian<'input, E>(self) -> Endian
3423         where
3424             E: Endianity,
3425             T: UnwindSection<EndianSlice<'input, E>>,
3426             T::Offset: UnwindOffset<usize>,
3427         {
3428             if E::default().is_big_endian() {
3429                 Endian::Big
3430             } else {
3431                 Endian::Little
3432             }
3433         }
3434 
section<'input, E>(self, contents: &'input [u8]) -> T where E: Endianity, T: UnwindSection<EndianSlice<'input, E>> + ReadSection<EndianSlice<'input, E>>, T::Offset: UnwindOffset<usize>,3435         fn section<'input, E>(self, contents: &'input [u8]) -> T
3436         where
3437             E: Endianity,
3438             T: UnwindSection<EndianSlice<'input, E>> + ReadSection<EndianSlice<'input, E>>,
3439             T::Offset: UnwindOffset<usize>,
3440         {
3441             EndianSlice::new(contents, E::default()).into()
3442         }
3443     }
3444 
debug_frame_le<'a>() -> SectionKind<DebugFrame<EndianSlice<'a, LittleEndian>>>3445     fn debug_frame_le<'a>() -> SectionKind<DebugFrame<EndianSlice<'a, LittleEndian>>> {
3446         SectionKind(PhantomData)
3447     }
3448 
debug_frame_be<'a>() -> SectionKind<DebugFrame<EndianSlice<'a, BigEndian>>>3449     fn debug_frame_be<'a>() -> SectionKind<DebugFrame<EndianSlice<'a, BigEndian>>> {
3450         SectionKind(PhantomData)
3451     }
3452 
eh_frame_le<'a>() -> SectionKind<EhFrame<EndianSlice<'a, LittleEndian>>>3453     fn eh_frame_le<'a>() -> SectionKind<EhFrame<EndianSlice<'a, LittleEndian>>> {
3454         SectionKind(PhantomData)
3455     }
3456 
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>>,3457     fn parse_fde<Section, O, F, R>(
3458         section: Section,
3459         input: &mut R,
3460         get_cie: F,
3461     ) -> Result<FrameDescriptionEntry<R>>
3462     where
3463         R: Reader,
3464         Section: UnwindSection<R, Offset = O>,
3465         O: UnwindOffset<R::Offset>,
3466         F: FnMut(&Section, &BaseAddresses, O) -> Result<CommonInformationEntry<R>>,
3467     {
3468         let bases = Default::default();
3469         match parse_cfi_entry(&bases, &section, input) {
3470             Ok(Some(CieOrFde::Fde(partial))) => partial.parse(get_cie),
3471             Ok(_) => Err(Error::NoEntryAtGivenOffset),
3472             Err(e) => Err(e),
3473         }
3474     }
3475 
3476     // Mixin methods for `Section` to help define binary test data.
3477 
3478     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: UnwindOffset3479         fn cie<'aug, 'input, E, T>(
3480             self,
3481             _kind: SectionKind<T>,
3482             augmentation: Option<&'aug str>,
3483             cie: &mut CommonInformationEntry<EndianSlice<'input, E>>,
3484         ) -> Self
3485         where
3486             E: Endianity,
3487             T: UnwindSection<EndianSlice<'input, E>>,
3488             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>3489         fn fde<'a, 'input, E, T, L>(
3490             self,
3491             _kind: SectionKind<T>,
3492             cie_offset: L,
3493             fde: &mut FrameDescriptionEntry<EndianSlice<'input, E>>,
3494         ) -> Self
3495         where
3496             E: Endianity,
3497             T: UnwindSection<EndianSlice<'input, E>>,
3498             T::Offset: UnwindOffset,
3499             L: ToLabelOrNum<'a, u64>;
3500     }
3501 
3502     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,3503         fn cie<'aug, 'input, E, T>(
3504             self,
3505             _kind: SectionKind<T>,
3506             augmentation: Option<&'aug str>,
3507             cie: &mut CommonInformationEntry<EndianSlice<'input, E>>,
3508         ) -> Self
3509         where
3510             E: Endianity,
3511             T: UnwindSection<EndianSlice<'input, E>>,
3512             T::Offset: UnwindOffset,
3513         {
3514             cie.offset = self.size() as _;
3515             let length = Label::new();
3516             let start = Label::new();
3517             let end = Label::new();
3518 
3519             let section = match cie.format {
3520                 Format::Dwarf32 => self.D32(&length).mark(&start).D32(0xffff_ffff),
3521                 Format::Dwarf64 => {
3522                     let section = self.D32(0xffff_ffff);
3523                     section.D64(&length).mark(&start).D64(0xffff_ffff_ffff_ffff)
3524                 }
3525             };
3526 
3527             let mut section = section.D8(cie.version);
3528 
3529             if let Some(augmentation) = augmentation {
3530                 section = section.append_bytes(augmentation.as_bytes());
3531             }
3532 
3533             // Null terminator for augmentation string.
3534             let section = section.D8(0);
3535 
3536             let section = if T::has_address_and_segment_sizes(cie.version) {
3537                 section.D8(cie.address_size).D8(cie.segment_size)
3538             } else {
3539                 section
3540             };
3541 
3542             let section = section
3543                 .uleb(cie.code_alignment_factor)
3544                 .sleb(cie.data_alignment_factor)
3545                 .uleb(cie.return_address_register.0.into())
3546                 .append_bytes(cie.initial_instructions.into())
3547                 .mark(&end);
3548 
3549             cie.length = (&end - &start) as usize;
3550             length.set_const(cie.length as u64);
3551 
3552             section
3553         }
3554 
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>,3555         fn fde<'a, 'input, E, T, L>(
3556             self,
3557             _kind: SectionKind<T>,
3558             cie_offset: L,
3559             fde: &mut FrameDescriptionEntry<EndianSlice<'input, E>>,
3560         ) -> Self
3561         where
3562             E: Endianity,
3563             T: UnwindSection<EndianSlice<'input, E>>,
3564             T::Offset: UnwindOffset,
3565             L: ToLabelOrNum<'a, u64>,
3566         {
3567             fde.offset = self.size() as _;
3568             let length = Label::new();
3569             let start = Label::new();
3570             let end = Label::new();
3571 
3572             assert_eq!(fde.format, fde.cie.format);
3573 
3574             let section = match T::cie_offset_encoding(fde.format) {
3575                 CieOffsetEncoding::U32 => {
3576                     let section = self.D32(&length).mark(&start);
3577                     match cie_offset.to_labelornum() {
3578                         LabelOrNum::Label(ref l) => section.D32(l),
3579                         LabelOrNum::Num(o) => section.D32(o as u32),
3580                     }
3581                 }
3582                 CieOffsetEncoding::U64 => {
3583                     let section = self.D32(0xffff_ffff);
3584                     section.D64(&length).mark(&start).D64(cie_offset)
3585                 }
3586             };
3587 
3588             let section = match fde.cie.segment_size {
3589                 0 => section,
3590                 4 => section.D32(fde.initial_segment as u32),
3591                 8 => section.D64(fde.initial_segment),
3592                 x => panic!("Unsupported test segment size: {}", x),
3593             };
3594 
3595             let section = match fde.cie.address_size {
3596                 4 => section
3597                     .D32(fde.initial_address() as u32)
3598                     .D32(fde.len() as u32),
3599                 8 => section.D64(fde.initial_address()).D64(fde.len()),
3600                 x => panic!("Unsupported address size: {}", x),
3601             };
3602 
3603             let section = if let Some(ref augmentation) = fde.augmentation {
3604                 let cie_aug = fde
3605                     .cie
3606                     .augmentation
3607                     .expect("FDE has augmentation, but CIE doesn't");
3608 
3609                 if let Some(lsda) = augmentation.lsda {
3610                     // We only support writing `DW_EH_PE_absptr` here.
3611                     assert_eq!(
3612                         cie_aug
3613                             .lsda
3614                             .expect("FDE has lsda, but CIE doesn't")
3615                             .format(),
3616                         constants::DW_EH_PE_absptr
3617                     );
3618 
3619                     // Augmentation data length
3620                     let section = section.uleb(u64::from(fde.cie.address_size));
3621                     match fde.cie.address_size {
3622                         4 => section.D32({
3623                             let x: u64 = lsda.into();
3624                             x as u32
3625                         }),
3626                         8 => section.D64({
3627                             let x: u64 = lsda.into();
3628                             x
3629                         }),
3630                         x => panic!("Unsupported address size: {}", x),
3631                     }
3632                 } else {
3633                     // Even if we don't have any augmentation data, if there is
3634                     // an augmentation defined, we need to put the length in.
3635                     section.uleb(0)
3636                 }
3637             } else {
3638                 section
3639             };
3640 
3641             let section = section.append_bytes(fde.instructions.into()).mark(&end);
3642 
3643             fde.length = (&end - &start) as usize;
3644             length.set_const(fde.length as u64);
3645 
3646             section
3647         }
3648     }
3649 
3650     trait ResultExt {
map_eof(self, input: &[u8]) -> Self3651         fn map_eof(self, input: &[u8]) -> Self;
3652     }
3653 
3654     impl<T> ResultExt for Result<T> {
map_eof(self, input: &[u8]) -> Self3655         fn map_eof(self, input: &[u8]) -> Self {
3656             match self {
3657                 Err(Error::UnexpectedEof(id)) => {
3658                     let id = ReaderOffsetId(id.0 - input.as_ptr() as u64);
3659                     Err(Error::UnexpectedEof(id))
3660                 }
3661                 r => r,
3662             }
3663         }
3664     }
3665 
3666     #[allow(clippy::type_complexity)]
3667     #[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,3668     fn assert_parse_cie<'input, E>(
3669         kind: SectionKind<DebugFrame<EndianSlice<'input, E>>>,
3670         section: Section,
3671         address_size: u8,
3672         expected: Result<(
3673             EndianSlice<'input, E>,
3674             CommonInformationEntry<EndianSlice<'input, E>>,
3675         )>,
3676     ) where
3677         E: Endianity,
3678     {
3679         let section = section.get_contents().unwrap();
3680         let mut debug_frame = kind.section(&section);
3681         debug_frame.set_address_size(address_size);
3682         let input = &mut EndianSlice::new(&section, E::default());
3683         let bases = Default::default();
3684         let result = CommonInformationEntry::parse(&bases, &debug_frame, input);
3685         let result = result.map(|cie| (*input, cie)).map_eof(&section);
3686         assert_eq!(result, expected);
3687     }
3688 
3689     #[test]
test_parse_cie_incomplete_length_32()3690     fn test_parse_cie_incomplete_length_32() {
3691         let kind = debug_frame_le();
3692         let section = Section::with_endian(kind.endian()).L16(5);
3693         assert_parse_cie(
3694             kind,
3695             section,
3696             8,
3697             Err(Error::UnexpectedEof(ReaderOffsetId(0))),
3698         );
3699     }
3700 
3701     #[test]
test_parse_cie_incomplete_length_64()3702     fn test_parse_cie_incomplete_length_64() {
3703         let kind = debug_frame_le();
3704         let section = Section::with_endian(kind.endian())
3705             .L32(0xffff_ffff)
3706             .L32(12345);
3707         assert_parse_cie(
3708             kind,
3709             section,
3710             8,
3711             Err(Error::UnexpectedEof(ReaderOffsetId(4))),
3712         );
3713     }
3714 
3715     #[test]
test_parse_cie_incomplete_id_32()3716     fn test_parse_cie_incomplete_id_32() {
3717         let kind = debug_frame_be();
3718         let section = Section::with_endian(kind.endian())
3719             // The length is not large enough to contain the ID.
3720             .B32(3)
3721             .B32(0xffff_ffff);
3722         assert_parse_cie(
3723             kind,
3724             section,
3725             8,
3726             Err(Error::UnexpectedEof(ReaderOffsetId(4))),
3727         );
3728     }
3729 
3730     #[test]
test_parse_cie_bad_id_32()3731     fn test_parse_cie_bad_id_32() {
3732         let kind = debug_frame_be();
3733         let section = Section::with_endian(kind.endian())
3734             // Initial length
3735             .B32(4)
3736             // Not the CIE Id.
3737             .B32(0xbad1_bad2);
3738         assert_parse_cie(kind, section, 8, Err(Error::NotCieId));
3739     }
3740 
3741     #[test]
test_parse_cie_32_bad_version()3742     fn test_parse_cie_32_bad_version() {
3743         let mut cie = CommonInformationEntry {
3744             offset: 0,
3745             length: 0,
3746             format: Format::Dwarf32,
3747             version: 99,
3748             augmentation: None,
3749             address_size: 4,
3750             segment_size: 0,
3751             code_alignment_factor: 1,
3752             data_alignment_factor: 2,
3753             return_address_register: Register(3),
3754             initial_instructions: EndianSlice::new(&[], LittleEndian),
3755         };
3756 
3757         let kind = debug_frame_le();
3758         let section = Section::with_endian(kind.endian()).cie(kind, None, &mut cie);
3759         assert_parse_cie(kind, section, 4, Err(Error::UnknownVersion(99)));
3760     }
3761 
3762     #[test]
test_parse_cie_unknown_augmentation()3763     fn test_parse_cie_unknown_augmentation() {
3764         let length = Label::new();
3765         let start = Label::new();
3766         let end = Label::new();
3767 
3768         let augmentation = Some("replicant");
3769         let expected_rest = [1, 2, 3];
3770 
3771         let kind = debug_frame_le();
3772         let section = Section::with_endian(kind.endian())
3773             // Initial length
3774             .L32(&length)
3775             .mark(&start)
3776             // CIE Id
3777             .L32(0xffff_ffff)
3778             // Version
3779             .D8(4)
3780             // Augmentation
3781             .append_bytes(augmentation.unwrap().as_bytes())
3782             // Null terminator
3783             .D8(0)
3784             // Extra augmented data that we can't understand.
3785             .L32(1)
3786             .L32(2)
3787             .L32(3)
3788             .L32(4)
3789             .L32(5)
3790             .L32(6)
3791             .mark(&end)
3792             .append_bytes(&expected_rest);
3793 
3794         let expected_length = (&end - &start) as u64;
3795         length.set_const(expected_length);
3796 
3797         assert_parse_cie(kind, section, 8, Err(Error::UnknownAugmentation));
3798     }
3799 
test_parse_cie(format: Format, version: u8, address_size: u8)3800     fn test_parse_cie(format: Format, version: u8, address_size: u8) {
3801         let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9];
3802         let expected_instrs: Vec<_> = (0..4).map(|_| constants::DW_CFA_nop.0).collect();
3803 
3804         let mut cie = CommonInformationEntry {
3805             offset: 0,
3806             length: 0,
3807             format,
3808             version,
3809             augmentation: None,
3810             address_size,
3811             segment_size: 0,
3812             code_alignment_factor: 16,
3813             data_alignment_factor: 32,
3814             return_address_register: Register(1),
3815             initial_instructions: EndianSlice::new(&expected_instrs, LittleEndian),
3816         };
3817 
3818         let kind = debug_frame_le();
3819         let section = Section::with_endian(kind.endian())
3820             .cie(kind, None, &mut cie)
3821             .append_bytes(&expected_rest);
3822 
3823         assert_parse_cie(
3824             kind,
3825             section,
3826             address_size,
3827             Ok((EndianSlice::new(&expected_rest, LittleEndian), cie)),
3828         );
3829     }
3830 
3831     #[test]
test_parse_cie_32_ok()3832     fn test_parse_cie_32_ok() {
3833         test_parse_cie(Format::Dwarf32, 1, 4);
3834         test_parse_cie(Format::Dwarf32, 1, 8);
3835         test_parse_cie(Format::Dwarf32, 4, 4);
3836         test_parse_cie(Format::Dwarf32, 4, 8);
3837     }
3838 
3839     #[test]
test_parse_cie_64_ok()3840     fn test_parse_cie_64_ok() {
3841         test_parse_cie(Format::Dwarf64, 1, 4);
3842         test_parse_cie(Format::Dwarf64, 1, 8);
3843         test_parse_cie(Format::Dwarf64, 4, 4);
3844         test_parse_cie(Format::Dwarf64, 4, 8);
3845     }
3846 
3847     #[test]
test_parse_cie_length_too_big()3848     fn test_parse_cie_length_too_big() {
3849         let expected_instrs: Vec<_> = (0..13).map(|_| constants::DW_CFA_nop.0).collect();
3850 
3851         let mut cie = CommonInformationEntry {
3852             offset: 0,
3853             length: 0,
3854             format: Format::Dwarf32,
3855             version: 4,
3856             augmentation: None,
3857             address_size: 4,
3858             segment_size: 0,
3859             code_alignment_factor: 0,
3860             data_alignment_factor: 0,
3861             return_address_register: Register(3),
3862             initial_instructions: EndianSlice::new(&expected_instrs, LittleEndian),
3863         };
3864 
3865         let kind = debug_frame_le();
3866         let section = Section::with_endian(kind.endian()).cie(kind, None, &mut cie);
3867 
3868         let mut contents = section.get_contents().unwrap();
3869 
3870         // Overwrite the length to be too big.
3871         contents[0] = 0;
3872         contents[1] = 0;
3873         contents[2] = 0;
3874         contents[3] = 255;
3875 
3876         let debug_frame = DebugFrame::new(&contents, LittleEndian);
3877         let bases = Default::default();
3878         assert_eq!(
3879             CommonInformationEntry::parse(
3880                 &bases,
3881                 &debug_frame,
3882                 &mut EndianSlice::new(&contents, LittleEndian)
3883             )
3884             .map_eof(&contents),
3885             Err(Error::UnexpectedEof(ReaderOffsetId(4)))
3886         );
3887     }
3888 
3889     #[test]
test_parse_fde_incomplete_length_32()3890     fn test_parse_fde_incomplete_length_32() {
3891         let kind = debug_frame_le();
3892         let section = Section::with_endian(kind.endian()).L16(5);
3893         let section = section.get_contents().unwrap();
3894         let debug_frame = kind.section(&section);
3895         let rest = &mut EndianSlice::new(&section, LittleEndian);
3896         assert_eq!(
3897             parse_fde(debug_frame, rest, UnwindSection::cie_from_offset).map_eof(&section),
3898             Err(Error::UnexpectedEof(ReaderOffsetId(0)))
3899         );
3900     }
3901 
3902     #[test]
test_parse_fde_incomplete_length_64()3903     fn test_parse_fde_incomplete_length_64() {
3904         let kind = debug_frame_le();
3905         let section = Section::with_endian(kind.endian())
3906             .L32(0xffff_ffff)
3907             .L32(12345);
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(4)))
3914         );
3915     }
3916 
3917     #[test]
test_parse_fde_incomplete_cie_pointer_32()3918     fn test_parse_fde_incomplete_cie_pointer_32() {
3919         let kind = debug_frame_be();
3920         let section = Section::with_endian(kind.endian())
3921             // The length is not large enough to contain the CIE pointer.
3922             .B32(3)
3923             .B32(1994);
3924         let section = section.get_contents().unwrap();
3925         let debug_frame = kind.section(&section);
3926         let rest = &mut EndianSlice::new(&section, BigEndian);
3927         assert_eq!(
3928             parse_fde(debug_frame, rest, UnwindSection::cie_from_offset).map_eof(&section),
3929             Err(Error::UnexpectedEof(ReaderOffsetId(4)))
3930         );
3931     }
3932 
3933     #[test]
test_parse_fde_32_ok()3934     fn test_parse_fde_32_ok() {
3935         let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9];
3936         let cie_offset = 0xbad0_bad1;
3937         let expected_instrs: Vec<_> = (0..7).map(|_| constants::DW_CFA_nop.0).collect();
3938 
3939         let cie = CommonInformationEntry {
3940             offset: 0,
3941             length: 100,
3942             format: Format::Dwarf32,
3943             version: 4,
3944             augmentation: None,
3945             // DWARF32 with a 64 bit address size! Holy moly!
3946             address_size: 8,
3947             segment_size: 0,
3948             code_alignment_factor: 3,
3949             data_alignment_factor: 2,
3950             return_address_register: Register(1),
3951             initial_instructions: EndianSlice::new(&[], LittleEndian),
3952         };
3953 
3954         let mut fde = FrameDescriptionEntry {
3955             offset: 0,
3956             length: 0,
3957             format: Format::Dwarf32,
3958             cie: cie.clone(),
3959             initial_segment: 0,
3960             initial_address: 0xfeed_beef,
3961             address_range: 39,
3962             augmentation: None,
3963             instructions: EndianSlice::new(&expected_instrs, LittleEndian),
3964         };
3965 
3966         let kind = debug_frame_le();
3967         let section = Section::with_endian(kind.endian())
3968             .fde(kind, cie_offset, &mut fde)
3969             .append_bytes(&expected_rest);
3970 
3971         let section = section.get_contents().unwrap();
3972         let debug_frame = kind.section(&section);
3973         let rest = &mut EndianSlice::new(&section, LittleEndian);
3974 
3975         let get_cie = |_: &_, _: &_, offset| {
3976             assert_eq!(offset, DebugFrameOffset(cie_offset as usize));
3977             Ok(cie.clone())
3978         };
3979 
3980         assert_eq!(parse_fde(debug_frame, rest, get_cie), Ok(fde));
3981         assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
3982     }
3983 
3984     #[test]
test_parse_fde_32_with_segment_ok()3985     fn test_parse_fde_32_with_segment_ok() {
3986         let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9];
3987         let cie_offset = 0xbad0_bad1;
3988         let expected_instrs: Vec<_> = (0..92).map(|_| constants::DW_CFA_nop.0).collect();
3989 
3990         let cie = CommonInformationEntry {
3991             offset: 0,
3992             length: 100,
3993             format: Format::Dwarf32,
3994             version: 4,
3995             augmentation: None,
3996             address_size: 4,
3997             segment_size: 4,
3998             code_alignment_factor: 3,
3999             data_alignment_factor: 2,
4000             return_address_register: Register(1),
4001             initial_instructions: EndianSlice::new(&[], LittleEndian),
4002         };
4003 
4004         let mut fde = FrameDescriptionEntry {
4005             offset: 0,
4006             length: 0,
4007             format: Format::Dwarf32,
4008             cie: cie.clone(),
4009             initial_segment: 0xbadb_ad11,
4010             initial_address: 0xfeed_beef,
4011             address_range: 999,
4012             augmentation: None,
4013             instructions: EndianSlice::new(&expected_instrs, LittleEndian),
4014         };
4015 
4016         let kind = debug_frame_le();
4017         let section = Section::with_endian(kind.endian())
4018             .fde(kind, cie_offset, &mut fde)
4019             .append_bytes(&expected_rest);
4020 
4021         let section = section.get_contents().unwrap();
4022         let debug_frame = kind.section(&section);
4023         let rest = &mut EndianSlice::new(&section, LittleEndian);
4024 
4025         let get_cie = |_: &_, _: &_, offset| {
4026             assert_eq!(offset, DebugFrameOffset(cie_offset as usize));
4027             Ok(cie.clone())
4028         };
4029 
4030         assert_eq!(parse_fde(debug_frame, rest, get_cie), Ok(fde));
4031         assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
4032     }
4033 
4034     #[test]
test_parse_fde_64_ok()4035     fn test_parse_fde_64_ok() {
4036         let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9];
4037         let cie_offset = 0xbad0_bad1;
4038         let expected_instrs: Vec<_> = (0..7).map(|_| constants::DW_CFA_nop.0).collect();
4039 
4040         let cie = CommonInformationEntry {
4041             offset: 0,
4042             length: 100,
4043             format: Format::Dwarf64,
4044             version: 4,
4045             augmentation: None,
4046             address_size: 8,
4047             segment_size: 0,
4048             code_alignment_factor: 3,
4049             data_alignment_factor: 2,
4050             return_address_register: Register(1),
4051             initial_instructions: EndianSlice::new(&[], LittleEndian),
4052         };
4053 
4054         let mut fde = FrameDescriptionEntry {
4055             offset: 0,
4056             length: 0,
4057             format: Format::Dwarf64,
4058             cie: cie.clone(),
4059             initial_segment: 0,
4060             initial_address: 0xfeed_beef,
4061             address_range: 999,
4062             augmentation: None,
4063             instructions: EndianSlice::new(&expected_instrs, LittleEndian),
4064         };
4065 
4066         let kind = debug_frame_le();
4067         let section = Section::with_endian(kind.endian())
4068             .fde(kind, cie_offset, &mut fde)
4069             .append_bytes(&expected_rest);
4070 
4071         let section = section.get_contents().unwrap();
4072         let debug_frame = kind.section(&section);
4073         let rest = &mut EndianSlice::new(&section, LittleEndian);
4074 
4075         let get_cie = |_: &_, _: &_, offset| {
4076             assert_eq!(offset, DebugFrameOffset(cie_offset as usize));
4077             Ok(cie.clone())
4078         };
4079 
4080         assert_eq!(parse_fde(debug_frame, rest, get_cie), Ok(fde));
4081         assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
4082     }
4083 
4084     #[test]
test_parse_cfi_entry_on_cie_32_ok()4085     fn test_parse_cfi_entry_on_cie_32_ok() {
4086         let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9];
4087         let expected_instrs: Vec<_> = (0..4).map(|_| constants::DW_CFA_nop.0).collect();
4088 
4089         let mut cie = CommonInformationEntry {
4090             offset: 0,
4091             length: 0,
4092             format: Format::Dwarf32,
4093             version: 4,
4094             augmentation: None,
4095             address_size: 4,
4096             segment_size: 0,
4097             code_alignment_factor: 16,
4098             data_alignment_factor: 32,
4099             return_address_register: Register(1),
4100             initial_instructions: EndianSlice::new(&expected_instrs, BigEndian),
4101         };
4102 
4103         let kind = debug_frame_be();
4104         let section = Section::with_endian(kind.endian())
4105             .cie(kind, None, &mut cie)
4106             .append_bytes(&expected_rest);
4107         let section = section.get_contents().unwrap();
4108         let debug_frame = kind.section(&section);
4109         let rest = &mut EndianSlice::new(&section, BigEndian);
4110 
4111         let bases = Default::default();
4112         assert_eq!(
4113             parse_cfi_entry(&bases, &debug_frame, rest),
4114             Ok(Some(CieOrFde::Cie(cie)))
4115         );
4116         assert_eq!(*rest, EndianSlice::new(&expected_rest, BigEndian));
4117     }
4118 
4119     #[test]
test_parse_cfi_entry_on_fde_32_ok()4120     fn test_parse_cfi_entry_on_fde_32_ok() {
4121         let cie_offset = 0x1234_5678;
4122         let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9];
4123         let expected_instrs: Vec<_> = (0..4).map(|_| constants::DW_CFA_nop.0).collect();
4124 
4125         let cie = CommonInformationEntry {
4126             offset: 0,
4127             length: 0,
4128             format: Format::Dwarf32,
4129             version: 4,
4130             augmentation: None,
4131             address_size: 4,
4132             segment_size: 0,
4133             code_alignment_factor: 16,
4134             data_alignment_factor: 32,
4135             return_address_register: Register(1),
4136             initial_instructions: EndianSlice::new(&[], BigEndian),
4137         };
4138 
4139         let mut fde = FrameDescriptionEntry {
4140             offset: 0,
4141             length: 0,
4142             format: Format::Dwarf32,
4143             cie: cie.clone(),
4144             initial_segment: 0,
4145             initial_address: 0xfeed_beef,
4146             address_range: 39,
4147             augmentation: None,
4148             instructions: EndianSlice::new(&expected_instrs, BigEndian),
4149         };
4150 
4151         let kind = debug_frame_be();
4152         let section = Section::with_endian(kind.endian())
4153             .fde(kind, cie_offset, &mut fde)
4154             .append_bytes(&expected_rest);
4155 
4156         let section = section.get_contents().unwrap();
4157         let debug_frame = kind.section(&section);
4158         let rest = &mut EndianSlice::new(&section, BigEndian);
4159 
4160         let bases = Default::default();
4161         match parse_cfi_entry(&bases, &debug_frame, rest) {
4162             Ok(Some(CieOrFde::Fde(partial))) => {
4163                 assert_eq!(*rest, EndianSlice::new(&expected_rest, BigEndian));
4164 
4165                 assert_eq!(partial.length, fde.length);
4166                 assert_eq!(partial.format, fde.format);
4167                 assert_eq!(partial.cie_offset, DebugFrameOffset(cie_offset as usize));
4168 
4169                 let get_cie = |_: &_, _: &_, offset| {
4170                     assert_eq!(offset, DebugFrameOffset(cie_offset as usize));
4171                     Ok(cie.clone())
4172                 };
4173 
4174                 assert_eq!(partial.parse(get_cie), Ok(fde));
4175             }
4176             otherwise => panic!("Unexpected result: {:#?}", otherwise),
4177         }
4178     }
4179 
4180     #[test]
test_cfi_entries_iter()4181     fn test_cfi_entries_iter() {
4182         let expected_instrs1: Vec<_> = (0..4).map(|_| constants::DW_CFA_nop.0).collect();
4183 
4184         let expected_instrs2: Vec<_> = (0..8).map(|_| constants::DW_CFA_nop.0).collect();
4185 
4186         let expected_instrs3: Vec<_> = (0..12).map(|_| constants::DW_CFA_nop.0).collect();
4187 
4188         let expected_instrs4: Vec<_> = (0..16).map(|_| constants::DW_CFA_nop.0).collect();
4189 
4190         let mut cie1 = CommonInformationEntry {
4191             offset: 0,
4192             length: 0,
4193             format: Format::Dwarf32,
4194             version: 4,
4195             augmentation: None,
4196             address_size: 4,
4197             segment_size: 0,
4198             code_alignment_factor: 1,
4199             data_alignment_factor: 2,
4200             return_address_register: Register(3),
4201             initial_instructions: EndianSlice::new(&expected_instrs1, BigEndian),
4202         };
4203 
4204         let mut cie2 = CommonInformationEntry {
4205             offset: 0,
4206             length: 0,
4207             format: Format::Dwarf32,
4208             version: 4,
4209             augmentation: None,
4210             address_size: 4,
4211             segment_size: 0,
4212             code_alignment_factor: 3,
4213             data_alignment_factor: 2,
4214             return_address_register: Register(1),
4215             initial_instructions: EndianSlice::new(&expected_instrs2, BigEndian),
4216         };
4217 
4218         let cie1_location = Label::new();
4219         let cie2_location = Label::new();
4220 
4221         // Write the CIEs first so that their length gets set before we clone
4222         // them into the FDEs and our equality assertions down the line end up
4223         // with all the CIEs always having he correct length.
4224         let kind = debug_frame_be();
4225         let section = Section::with_endian(kind.endian())
4226             .mark(&cie1_location)
4227             .cie(kind, None, &mut cie1)
4228             .mark(&cie2_location)
4229             .cie(kind, None, &mut cie2);
4230 
4231         let mut fde1 = FrameDescriptionEntry {
4232             offset: 0,
4233             length: 0,
4234             format: Format::Dwarf32,
4235             cie: cie1.clone(),
4236             initial_segment: 0,
4237             initial_address: 0xfeed_beef,
4238             address_range: 39,
4239             augmentation: None,
4240             instructions: EndianSlice::new(&expected_instrs3, BigEndian),
4241         };
4242 
4243         let mut fde2 = FrameDescriptionEntry {
4244             offset: 0,
4245             length: 0,
4246             format: Format::Dwarf32,
4247             cie: cie2.clone(),
4248             initial_segment: 0,
4249             initial_address: 0xfeed_face,
4250             address_range: 9000,
4251             augmentation: None,
4252             instructions: EndianSlice::new(&expected_instrs4, BigEndian),
4253         };
4254 
4255         let section =
4256             section
4257                 .fde(kind, &cie1_location, &mut fde1)
4258                 .fde(kind, &cie2_location, &mut fde2);
4259 
4260         section.start().set_const(0);
4261 
4262         let cie1_offset = cie1_location.value().unwrap() as usize;
4263         let cie2_offset = cie2_location.value().unwrap() as usize;
4264 
4265         let contents = section.get_contents().unwrap();
4266         let debug_frame = kind.section(&contents);
4267 
4268         let bases = Default::default();
4269         let mut entries = debug_frame.entries(&bases);
4270 
4271         assert_eq!(entries.next(), Ok(Some(CieOrFde::Cie(cie1.clone()))));
4272         assert_eq!(entries.next(), Ok(Some(CieOrFde::Cie(cie2.clone()))));
4273 
4274         match entries.next() {
4275             Ok(Some(CieOrFde::Fde(partial))) => {
4276                 assert_eq!(partial.length, fde1.length);
4277                 assert_eq!(partial.format, fde1.format);
4278                 assert_eq!(partial.cie_offset, DebugFrameOffset(cie1_offset));
4279 
4280                 let get_cie = |_: &_, _: &_, offset| {
4281                     assert_eq!(offset, DebugFrameOffset(cie1_offset));
4282                     Ok(cie1.clone())
4283                 };
4284                 assert_eq!(partial.parse(get_cie), Ok(fde1));
4285             }
4286             otherwise => panic!("Unexpected result: {:#?}", otherwise),
4287         }
4288 
4289         match entries.next() {
4290             Ok(Some(CieOrFde::Fde(partial))) => {
4291                 assert_eq!(partial.length, fde2.length);
4292                 assert_eq!(partial.format, fde2.format);
4293                 assert_eq!(partial.cie_offset, DebugFrameOffset(cie2_offset));
4294 
4295                 let get_cie = |_: &_, _: &_, offset| {
4296                     assert_eq!(offset, DebugFrameOffset(cie2_offset));
4297                     Ok(cie2.clone())
4298                 };
4299                 assert_eq!(partial.parse(get_cie), Ok(fde2));
4300             }
4301             otherwise => panic!("Unexpected result: {:#?}", otherwise),
4302         }
4303 
4304         assert_eq!(entries.next(), Ok(None));
4305     }
4306 
4307     #[test]
test_parse_cie_from_offset()4308     fn test_parse_cie_from_offset() {
4309         let filler = [1, 2, 3, 4, 5, 6, 7, 8, 9];
4310         let instrs: Vec<_> = (0..5).map(|_| constants::DW_CFA_nop.0).collect();
4311 
4312         let mut cie = CommonInformationEntry {
4313             offset: 0,
4314             length: 0,
4315             format: Format::Dwarf64,
4316             version: 4,
4317             augmentation: None,
4318             address_size: 4,
4319             segment_size: 0,
4320             code_alignment_factor: 4,
4321             data_alignment_factor: 8,
4322             return_address_register: Register(12),
4323             initial_instructions: EndianSlice::new(&instrs, LittleEndian),
4324         };
4325 
4326         let cie_location = Label::new();
4327 
4328         let kind = debug_frame_le();
4329         let section = Section::with_endian(kind.endian())
4330             .append_bytes(&filler)
4331             .mark(&cie_location)
4332             .cie(kind, None, &mut cie)
4333             .append_bytes(&filler);
4334 
4335         section.start().set_const(0);
4336 
4337         let cie_offset = DebugFrameOffset(cie_location.value().unwrap() as usize);
4338 
4339         let contents = section.get_contents().unwrap();
4340         let debug_frame = kind.section(&contents);
4341         let bases = Default::default();
4342 
4343         assert_eq!(debug_frame.cie_from_offset(&bases, cie_offset), Ok(cie));
4344     }
4345 
parse_cfi_instruction<R: Reader + Default>( input: &mut R, address_size: u8, ) -> Result<CallFrameInstruction<R>>4346     fn parse_cfi_instruction<R: Reader + Default>(
4347         input: &mut R,
4348         address_size: u8,
4349     ) -> Result<CallFrameInstruction<R>> {
4350         let parameters = &PointerEncodingParameters {
4351             bases: &SectionBaseAddresses::default(),
4352             func_base: None,
4353             address_size,
4354             section: &R::default(),
4355         };
4356         CallFrameInstruction::parse(input, None, parameters)
4357     }
4358 
4359     #[test]
test_parse_cfi_instruction_advance_loc()4360     fn test_parse_cfi_instruction_advance_loc() {
4361         let expected_rest = [1, 2, 3, 4];
4362         let expected_delta = 42;
4363         let section = Section::with_endian(Endian::Little)
4364             .D8(constants::DW_CFA_advance_loc.0 | expected_delta)
4365             .append_bytes(&expected_rest);
4366         let contents = section.get_contents().unwrap();
4367         let input = &mut EndianSlice::new(&contents, LittleEndian);
4368         assert_eq!(
4369             parse_cfi_instruction(input, 8),
4370             Ok(CallFrameInstruction::AdvanceLoc {
4371                 delta: u32::from(expected_delta),
4372             })
4373         );
4374         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4375     }
4376 
4377     #[test]
test_parse_cfi_instruction_offset()4378     fn test_parse_cfi_instruction_offset() {
4379         let expected_rest = [1, 2, 3, 4];
4380         let expected_reg = 3;
4381         let expected_offset = 1997;
4382         let section = Section::with_endian(Endian::Little)
4383             .D8(constants::DW_CFA_offset.0 | expected_reg)
4384             .uleb(expected_offset)
4385             .append_bytes(&expected_rest);
4386         let contents = section.get_contents().unwrap();
4387         let input = &mut EndianSlice::new(&contents, LittleEndian);
4388         assert_eq!(
4389             parse_cfi_instruction(input, 8),
4390             Ok(CallFrameInstruction::Offset {
4391                 register: Register(expected_reg.into()),
4392                 factored_offset: expected_offset,
4393             })
4394         );
4395         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4396     }
4397 
4398     #[test]
test_parse_cfi_instruction_restore()4399     fn test_parse_cfi_instruction_restore() {
4400         let expected_rest = [1, 2, 3, 4];
4401         let expected_reg = 3;
4402         let section = Section::with_endian(Endian::Little)
4403             .D8(constants::DW_CFA_restore.0 | expected_reg)
4404             .append_bytes(&expected_rest);
4405         let contents = section.get_contents().unwrap();
4406         let input = &mut EndianSlice::new(&contents, LittleEndian);
4407         assert_eq!(
4408             parse_cfi_instruction(input, 8),
4409             Ok(CallFrameInstruction::Restore {
4410                 register: Register(expected_reg.into()),
4411             })
4412         );
4413         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4414     }
4415 
4416     #[test]
test_parse_cfi_instruction_nop()4417     fn test_parse_cfi_instruction_nop() {
4418         let expected_rest = [1, 2, 3, 4];
4419         let section = Section::with_endian(Endian::Little)
4420             .D8(constants::DW_CFA_nop.0)
4421             .append_bytes(&expected_rest);
4422         let contents = section.get_contents().unwrap();
4423         let input = &mut EndianSlice::new(&contents, LittleEndian);
4424         assert_eq!(
4425             parse_cfi_instruction(input, 8),
4426             Ok(CallFrameInstruction::Nop)
4427         );
4428         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4429     }
4430 
4431     #[test]
test_parse_cfi_instruction_set_loc()4432     fn test_parse_cfi_instruction_set_loc() {
4433         let expected_rest = [1, 2, 3, 4];
4434         let expected_addr = 0xdead_beef;
4435         let section = Section::with_endian(Endian::Little)
4436             .D8(constants::DW_CFA_set_loc.0)
4437             .L64(expected_addr)
4438             .append_bytes(&expected_rest);
4439         let contents = section.get_contents().unwrap();
4440         let input = &mut EndianSlice::new(&contents, LittleEndian);
4441         assert_eq!(
4442             parse_cfi_instruction(input, 8),
4443             Ok(CallFrameInstruction::SetLoc {
4444                 address: expected_addr,
4445             })
4446         );
4447         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4448     }
4449 
4450     #[test]
test_parse_cfi_instruction_set_loc_encoding()4451     fn test_parse_cfi_instruction_set_loc_encoding() {
4452         let text_base = 0xfeed_face;
4453         let addr_offset = 0xbeef;
4454         let expected_addr = text_base + addr_offset;
4455         let expected_rest = [1, 2, 3, 4];
4456         let section = Section::with_endian(Endian::Little)
4457             .D8(constants::DW_CFA_set_loc.0)
4458             .L64(addr_offset)
4459             .append_bytes(&expected_rest);
4460         let contents = section.get_contents().unwrap();
4461         let input = &mut EndianSlice::new(&contents, LittleEndian);
4462         let parameters = &PointerEncodingParameters {
4463             bases: &BaseAddresses::default().set_text(text_base).eh_frame,
4464             func_base: None,
4465             address_size: 8,
4466             section: &EndianSlice::new(&[], LittleEndian),
4467         };
4468         assert_eq!(
4469             CallFrameInstruction::parse(input, Some(constants::DW_EH_PE_textrel), parameters),
4470             Ok(CallFrameInstruction::SetLoc {
4471                 address: expected_addr,
4472             })
4473         );
4474         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4475     }
4476 
4477     #[test]
test_parse_cfi_instruction_advance_loc1()4478     fn test_parse_cfi_instruction_advance_loc1() {
4479         let expected_rest = [1, 2, 3, 4];
4480         let expected_delta = 8;
4481         let section = Section::with_endian(Endian::Little)
4482             .D8(constants::DW_CFA_advance_loc1.0)
4483             .D8(expected_delta)
4484             .append_bytes(&expected_rest);
4485         let contents = section.get_contents().unwrap();
4486         let input = &mut EndianSlice::new(&contents, LittleEndian);
4487         assert_eq!(
4488             parse_cfi_instruction(input, 8),
4489             Ok(CallFrameInstruction::AdvanceLoc {
4490                 delta: u32::from(expected_delta),
4491             })
4492         );
4493         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4494     }
4495 
4496     #[test]
test_parse_cfi_instruction_advance_loc2()4497     fn test_parse_cfi_instruction_advance_loc2() {
4498         let expected_rest = [1, 2, 3, 4];
4499         let expected_delta = 500;
4500         let section = Section::with_endian(Endian::Little)
4501             .D8(constants::DW_CFA_advance_loc2.0)
4502             .L16(expected_delta)
4503             .append_bytes(&expected_rest);
4504         let contents = section.get_contents().unwrap();
4505         let input = &mut EndianSlice::new(&contents, LittleEndian);
4506         assert_eq!(
4507             parse_cfi_instruction(input, 8),
4508             Ok(CallFrameInstruction::AdvanceLoc {
4509                 delta: u32::from(expected_delta),
4510             })
4511         );
4512         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4513     }
4514 
4515     #[test]
test_parse_cfi_instruction_advance_loc4()4516     fn test_parse_cfi_instruction_advance_loc4() {
4517         let expected_rest = [1, 2, 3, 4];
4518         let expected_delta = 1 << 20;
4519         let section = Section::with_endian(Endian::Little)
4520             .D8(constants::DW_CFA_advance_loc4.0)
4521             .L32(expected_delta)
4522             .append_bytes(&expected_rest);
4523         let contents = section.get_contents().unwrap();
4524         let input = &mut EndianSlice::new(&contents, LittleEndian);
4525         assert_eq!(
4526             parse_cfi_instruction(input, 8),
4527             Ok(CallFrameInstruction::AdvanceLoc {
4528                 delta: expected_delta,
4529             })
4530         );
4531         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4532     }
4533 
4534     #[test]
test_parse_cfi_instruction_offset_extended()4535     fn test_parse_cfi_instruction_offset_extended() {
4536         let expected_rest = [1, 2, 3, 4];
4537         let expected_reg = 7;
4538         let expected_offset = 33;
4539         let section = Section::with_endian(Endian::Little)
4540             .D8(constants::DW_CFA_offset_extended.0)
4541             .uleb(expected_reg.into())
4542             .uleb(expected_offset)
4543             .append_bytes(&expected_rest);
4544         let contents = section.get_contents().unwrap();
4545         let input = &mut EndianSlice::new(&contents, LittleEndian);
4546         assert_eq!(
4547             parse_cfi_instruction(input, 8),
4548             Ok(CallFrameInstruction::Offset {
4549                 register: Register(expected_reg),
4550                 factored_offset: expected_offset,
4551             })
4552         );
4553         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4554     }
4555 
4556     #[test]
test_parse_cfi_instruction_restore_extended()4557     fn test_parse_cfi_instruction_restore_extended() {
4558         let expected_rest = [1, 2, 3, 4];
4559         let expected_reg = 7;
4560         let section = Section::with_endian(Endian::Little)
4561             .D8(constants::DW_CFA_restore_extended.0)
4562             .uleb(expected_reg.into())
4563             .append_bytes(&expected_rest);
4564         let contents = section.get_contents().unwrap();
4565         let input = &mut EndianSlice::new(&contents, LittleEndian);
4566         assert_eq!(
4567             parse_cfi_instruction(input, 8),
4568             Ok(CallFrameInstruction::Restore {
4569                 register: Register(expected_reg),
4570             })
4571         );
4572         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4573     }
4574 
4575     #[test]
test_parse_cfi_instruction_undefined()4576     fn test_parse_cfi_instruction_undefined() {
4577         let expected_rest = [1, 2, 3, 4];
4578         let expected_reg = 7;
4579         let section = Section::with_endian(Endian::Little)
4580             .D8(constants::DW_CFA_undefined.0)
4581             .uleb(expected_reg.into())
4582             .append_bytes(&expected_rest);
4583         let contents = section.get_contents().unwrap();
4584         let input = &mut EndianSlice::new(&contents, LittleEndian);
4585         assert_eq!(
4586             parse_cfi_instruction(input, 8),
4587             Ok(CallFrameInstruction::Undefined {
4588                 register: Register(expected_reg),
4589             })
4590         );
4591         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4592     }
4593 
4594     #[test]
test_parse_cfi_instruction_same_value()4595     fn test_parse_cfi_instruction_same_value() {
4596         let expected_rest = [1, 2, 3, 4];
4597         let expected_reg = 7;
4598         let section = Section::with_endian(Endian::Little)
4599             .D8(constants::DW_CFA_same_value.0)
4600             .uleb(expected_reg.into())
4601             .append_bytes(&expected_rest);
4602         let contents = section.get_contents().unwrap();
4603         let input = &mut EndianSlice::new(&contents, LittleEndian);
4604         assert_eq!(
4605             parse_cfi_instruction(input, 8),
4606             Ok(CallFrameInstruction::SameValue {
4607                 register: Register(expected_reg),
4608             })
4609         );
4610         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4611     }
4612 
4613     #[test]
test_parse_cfi_instruction_register()4614     fn test_parse_cfi_instruction_register() {
4615         let expected_rest = [1, 2, 3, 4];
4616         let expected_dest_reg = 7;
4617         let expected_src_reg = 8;
4618         let section = Section::with_endian(Endian::Little)
4619             .D8(constants::DW_CFA_register.0)
4620             .uleb(expected_dest_reg.into())
4621             .uleb(expected_src_reg.into())
4622             .append_bytes(&expected_rest);
4623         let contents = section.get_contents().unwrap();
4624         let input = &mut EndianSlice::new(&contents, LittleEndian);
4625         assert_eq!(
4626             parse_cfi_instruction(input, 8),
4627             Ok(CallFrameInstruction::Register {
4628                 dest_register: Register(expected_dest_reg),
4629                 src_register: Register(expected_src_reg),
4630             })
4631         );
4632         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4633     }
4634 
4635     #[test]
test_parse_cfi_instruction_remember_state()4636     fn test_parse_cfi_instruction_remember_state() {
4637         let expected_rest = [1, 2, 3, 4];
4638         let section = Section::with_endian(Endian::Little)
4639             .D8(constants::DW_CFA_remember_state.0)
4640             .append_bytes(&expected_rest);
4641         let contents = section.get_contents().unwrap();
4642         let input = &mut EndianSlice::new(&contents, LittleEndian);
4643         assert_eq!(
4644             parse_cfi_instruction(input, 8),
4645             Ok(CallFrameInstruction::RememberState)
4646         );
4647         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4648     }
4649 
4650     #[test]
test_parse_cfi_instruction_restore_state()4651     fn test_parse_cfi_instruction_restore_state() {
4652         let expected_rest = [1, 2, 3, 4];
4653         let section = Section::with_endian(Endian::Little)
4654             .D8(constants::DW_CFA_restore_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::RestoreState)
4661         );
4662         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4663     }
4664 
4665     #[test]
test_parse_cfi_instruction_def_cfa()4666     fn test_parse_cfi_instruction_def_cfa() {
4667         let expected_rest = [1, 2, 3, 4];
4668         let expected_reg = 2;
4669         let expected_offset = 0;
4670         let section = Section::with_endian(Endian::Little)
4671             .D8(constants::DW_CFA_def_cfa.0)
4672             .uleb(expected_reg.into())
4673             .uleb(expected_offset)
4674             .append_bytes(&expected_rest);
4675         let contents = section.get_contents().unwrap();
4676         let input = &mut EndianSlice::new(&contents, LittleEndian);
4677         assert_eq!(
4678             parse_cfi_instruction(input, 8),
4679             Ok(CallFrameInstruction::DefCfa {
4680                 register: Register(expected_reg),
4681                 offset: expected_offset,
4682             })
4683         );
4684         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4685     }
4686 
4687     #[test]
test_parse_cfi_instruction_def_cfa_register()4688     fn test_parse_cfi_instruction_def_cfa_register() {
4689         let expected_rest = [1, 2, 3, 4];
4690         let expected_reg = 2;
4691         let section = Section::with_endian(Endian::Little)
4692             .D8(constants::DW_CFA_def_cfa_register.0)
4693             .uleb(expected_reg.into())
4694             .append_bytes(&expected_rest);
4695         let contents = section.get_contents().unwrap();
4696         let input = &mut EndianSlice::new(&contents, LittleEndian);
4697         assert_eq!(
4698             parse_cfi_instruction(input, 8),
4699             Ok(CallFrameInstruction::DefCfaRegister {
4700                 register: Register(expected_reg),
4701             })
4702         );
4703         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4704     }
4705 
4706     #[test]
test_parse_cfi_instruction_def_cfa_offset()4707     fn test_parse_cfi_instruction_def_cfa_offset() {
4708         let expected_rest = [1, 2, 3, 4];
4709         let expected_offset = 23;
4710         let section = Section::with_endian(Endian::Little)
4711             .D8(constants::DW_CFA_def_cfa_offset.0)
4712             .uleb(expected_offset)
4713             .append_bytes(&expected_rest);
4714         let contents = section.get_contents().unwrap();
4715         let input = &mut EndianSlice::new(&contents, LittleEndian);
4716         assert_eq!(
4717             parse_cfi_instruction(input, 8),
4718             Ok(CallFrameInstruction::DefCfaOffset {
4719                 offset: expected_offset,
4720             })
4721         );
4722         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4723     }
4724 
4725     #[test]
test_parse_cfi_instruction_def_cfa_expression()4726     fn test_parse_cfi_instruction_def_cfa_expression() {
4727         let expected_rest = [1, 2, 3, 4];
4728         let expected_expr = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
4729 
4730         let length = Label::new();
4731         let start = Label::new();
4732         let end = Label::new();
4733 
4734         let section = Section::with_endian(Endian::Little)
4735             .D8(constants::DW_CFA_def_cfa_expression.0)
4736             .D8(&length)
4737             .mark(&start)
4738             .append_bytes(&expected_expr)
4739             .mark(&end)
4740             .append_bytes(&expected_rest);
4741 
4742         length.set_const((&end - &start) as u64);
4743         let contents = section.get_contents().unwrap();
4744         let input = &mut EndianSlice::new(&contents, LittleEndian);
4745 
4746         assert_eq!(
4747             parse_cfi_instruction(input, 8),
4748             Ok(CallFrameInstruction::DefCfaExpression {
4749                 expression: Expression(EndianSlice::new(&expected_expr, LittleEndian)),
4750             })
4751         );
4752         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4753     }
4754 
4755     #[test]
test_parse_cfi_instruction_expression()4756     fn test_parse_cfi_instruction_expression() {
4757         let expected_rest = [1, 2, 3, 4];
4758         let expected_reg = 99;
4759         let expected_expr = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
4760 
4761         let length = Label::new();
4762         let start = Label::new();
4763         let end = Label::new();
4764 
4765         let section = Section::with_endian(Endian::Little)
4766             .D8(constants::DW_CFA_expression.0)
4767             .uleb(expected_reg.into())
4768             .D8(&length)
4769             .mark(&start)
4770             .append_bytes(&expected_expr)
4771             .mark(&end)
4772             .append_bytes(&expected_rest);
4773 
4774         length.set_const((&end - &start) as u64);
4775         let contents = section.get_contents().unwrap();
4776         let input = &mut EndianSlice::new(&contents, LittleEndian);
4777 
4778         assert_eq!(
4779             parse_cfi_instruction(input, 8),
4780             Ok(CallFrameInstruction::Expression {
4781                 register: Register(expected_reg),
4782                 expression: Expression(EndianSlice::new(&expected_expr, LittleEndian)),
4783             })
4784         );
4785         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4786     }
4787 
4788     #[test]
test_parse_cfi_instruction_offset_extended_sf()4789     fn test_parse_cfi_instruction_offset_extended_sf() {
4790         let expected_rest = [1, 2, 3, 4];
4791         let expected_reg = 7;
4792         let expected_offset = -33;
4793         let section = Section::with_endian(Endian::Little)
4794             .D8(constants::DW_CFA_offset_extended_sf.0)
4795             .uleb(expected_reg.into())
4796             .sleb(expected_offset)
4797             .append_bytes(&expected_rest);
4798         let contents = section.get_contents().unwrap();
4799         let input = &mut EndianSlice::new(&contents, LittleEndian);
4800         assert_eq!(
4801             parse_cfi_instruction(input, 8),
4802             Ok(CallFrameInstruction::OffsetExtendedSf {
4803                 register: Register(expected_reg),
4804                 factored_offset: expected_offset,
4805             })
4806         );
4807         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4808     }
4809 
4810     #[test]
test_parse_cfi_instruction_def_cfa_sf()4811     fn test_parse_cfi_instruction_def_cfa_sf() {
4812         let expected_rest = [1, 2, 3, 4];
4813         let expected_reg = 2;
4814         let expected_offset = -9999;
4815         let section = Section::with_endian(Endian::Little)
4816             .D8(constants::DW_CFA_def_cfa_sf.0)
4817             .uleb(expected_reg.into())
4818             .sleb(expected_offset)
4819             .append_bytes(&expected_rest);
4820         let contents = section.get_contents().unwrap();
4821         let input = &mut EndianSlice::new(&contents, LittleEndian);
4822         assert_eq!(
4823             parse_cfi_instruction(input, 8),
4824             Ok(CallFrameInstruction::DefCfaSf {
4825                 register: Register(expected_reg),
4826                 factored_offset: expected_offset,
4827             })
4828         );
4829         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4830     }
4831 
4832     #[test]
test_parse_cfi_instruction_def_cfa_offset_sf()4833     fn test_parse_cfi_instruction_def_cfa_offset_sf() {
4834         let expected_rest = [1, 2, 3, 4];
4835         let expected_offset = -123;
4836         let section = Section::with_endian(Endian::Little)
4837             .D8(constants::DW_CFA_def_cfa_offset_sf.0)
4838             .sleb(expected_offset)
4839             .append_bytes(&expected_rest);
4840         let contents = section.get_contents().unwrap();
4841         let input = &mut EndianSlice::new(&contents, LittleEndian);
4842         assert_eq!(
4843             parse_cfi_instruction(input, 8),
4844             Ok(CallFrameInstruction::DefCfaOffsetSf {
4845                 factored_offset: expected_offset,
4846             })
4847         );
4848         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4849     }
4850 
4851     #[test]
test_parse_cfi_instruction_val_offset()4852     fn test_parse_cfi_instruction_val_offset() {
4853         let expected_rest = [1, 2, 3, 4];
4854         let expected_reg = 50;
4855         let expected_offset = 23;
4856         let section = Section::with_endian(Endian::Little)
4857             .D8(constants::DW_CFA_val_offset.0)
4858             .uleb(expected_reg.into())
4859             .uleb(expected_offset)
4860             .append_bytes(&expected_rest);
4861         let contents = section.get_contents().unwrap();
4862         let input = &mut EndianSlice::new(&contents, LittleEndian);
4863         assert_eq!(
4864             parse_cfi_instruction(input, 8),
4865             Ok(CallFrameInstruction::ValOffset {
4866                 register: Register(expected_reg),
4867                 factored_offset: expected_offset,
4868             })
4869         );
4870         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4871     }
4872 
4873     #[test]
test_parse_cfi_instruction_val_offset_sf()4874     fn test_parse_cfi_instruction_val_offset_sf() {
4875         let expected_rest = [1, 2, 3, 4];
4876         let expected_reg = 50;
4877         let expected_offset = -23;
4878         let section = Section::with_endian(Endian::Little)
4879             .D8(constants::DW_CFA_val_offset_sf.0)
4880             .uleb(expected_reg.into())
4881             .sleb(expected_offset)
4882             .append_bytes(&expected_rest);
4883         let contents = section.get_contents().unwrap();
4884         let input = &mut EndianSlice::new(&contents, LittleEndian);
4885         assert_eq!(
4886             parse_cfi_instruction(input, 8),
4887             Ok(CallFrameInstruction::ValOffsetSf {
4888                 register: Register(expected_reg),
4889                 factored_offset: expected_offset,
4890             })
4891         );
4892         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4893     }
4894 
4895     #[test]
test_parse_cfi_instruction_val_expression()4896     fn test_parse_cfi_instruction_val_expression() {
4897         let expected_rest = [1, 2, 3, 4];
4898         let expected_reg = 50;
4899         let expected_expr = [2, 2, 1, 1, 5, 5];
4900 
4901         let length = Label::new();
4902         let start = Label::new();
4903         let end = Label::new();
4904 
4905         let section = Section::with_endian(Endian::Little)
4906             .D8(constants::DW_CFA_val_expression.0)
4907             .uleb(expected_reg.into())
4908             .D8(&length)
4909             .mark(&start)
4910             .append_bytes(&expected_expr)
4911             .mark(&end)
4912             .append_bytes(&expected_rest);
4913 
4914         length.set_const((&end - &start) as u64);
4915         let contents = section.get_contents().unwrap();
4916         let input = &mut EndianSlice::new(&contents, LittleEndian);
4917 
4918         assert_eq!(
4919             parse_cfi_instruction(input, 8),
4920             Ok(CallFrameInstruction::ValExpression {
4921                 register: Register(expected_reg),
4922                 expression: Expression(EndianSlice::new(&expected_expr, LittleEndian)),
4923             })
4924         );
4925         assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
4926     }
4927 
4928     #[test]
test_parse_cfi_instruction_unknown_instruction()4929     fn test_parse_cfi_instruction_unknown_instruction() {
4930         let expected_rest = [1, 2, 3, 4];
4931         let unknown_instr = constants::DwCfa(0b0011_1111);
4932         let section = Section::with_endian(Endian::Little)
4933             .D8(unknown_instr.0)
4934             .append_bytes(&expected_rest);
4935         let contents = section.get_contents().unwrap();
4936         let input = &mut EndianSlice::new(&contents, LittleEndian);
4937         assert_eq!(
4938             parse_cfi_instruction(input, 8),
4939             Err(Error::UnknownCallFrameInstruction(unknown_instr))
4940         );
4941     }
4942 
4943     #[test]
test_call_frame_instruction_iter_ok()4944     fn test_call_frame_instruction_iter_ok() {
4945         let expected_reg = 50;
4946         let expected_expr = [2, 2, 1, 1, 5, 5];
4947         let expected_delta = 230;
4948 
4949         let length = Label::new();
4950         let start = Label::new();
4951         let end = Label::new();
4952 
4953         let section = Section::with_endian(Endian::Big)
4954             .D8(constants::DW_CFA_val_expression.0)
4955             .uleb(expected_reg.into())
4956             .D8(&length)
4957             .mark(&start)
4958             .append_bytes(&expected_expr)
4959             .mark(&end)
4960             .D8(constants::DW_CFA_advance_loc1.0)
4961             .D8(expected_delta);
4962 
4963         length.set_const((&end - &start) as u64);
4964         let contents = section.get_contents().unwrap();
4965         let input = EndianSlice::new(&contents, BigEndian);
4966         let parameters = PointerEncodingParameters {
4967             bases: &SectionBaseAddresses::default(),
4968             func_base: None,
4969             address_size: 8,
4970             section: &EndianSlice::default(),
4971         };
4972         let mut iter = CallFrameInstructionIter {
4973             input,
4974             address_encoding: None,
4975             parameters,
4976         };
4977 
4978         assert_eq!(
4979             iter.next(),
4980             Ok(Some(CallFrameInstruction::ValExpression {
4981                 register: Register(expected_reg),
4982                 expression: Expression(EndianSlice::new(&expected_expr, BigEndian)),
4983             }))
4984         );
4985 
4986         assert_eq!(
4987             iter.next(),
4988             Ok(Some(CallFrameInstruction::AdvanceLoc {
4989                 delta: u32::from(expected_delta),
4990             }))
4991         );
4992 
4993         assert_eq!(iter.next(), Ok(None));
4994     }
4995 
4996     #[test]
test_call_frame_instruction_iter_err()4997     fn test_call_frame_instruction_iter_err() {
4998         // DW_CFA_advance_loc1 without an operand.
4999         let section = Section::with_endian(Endian::Big).D8(constants::DW_CFA_advance_loc1.0);
5000 
5001         let contents = section.get_contents().unwrap();
5002         let input = EndianSlice::new(&contents, BigEndian);
5003         let parameters = PointerEncodingParameters {
5004             bases: &SectionBaseAddresses::default(),
5005             func_base: None,
5006             address_size: 8,
5007             section: &EndianSlice::default(),
5008         };
5009         let mut iter = CallFrameInstructionIter {
5010             input,
5011             address_encoding: None,
5012             parameters,
5013         };
5014 
5015         assert_eq!(
5016             iter.next().map_eof(&contents),
5017             Err(Error::UnexpectedEof(ReaderOffsetId(1)))
5018         );
5019         assert_eq!(iter.next(), Ok(None));
5020     }
5021 
5022     #[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>>, )], >,5023     fn assert_eval<'a, I>(
5024         mut initial_ctx: UnwindContext<EndianSlice<'a, LittleEndian>>,
5025         expected_ctx: UnwindContext<EndianSlice<'a, LittleEndian>>,
5026         cie: CommonInformationEntry<EndianSlice<'a, LittleEndian>>,
5027         fde: Option<FrameDescriptionEntry<EndianSlice<'a, LittleEndian>>>,
5028         instructions: I,
5029     ) where
5030         I: AsRef<
5031             [(
5032                 Result<bool>,
5033                 CallFrameInstruction<EndianSlice<'a, LittleEndian>>,
5034             )],
5035         >,
5036     {
5037         {
5038             let section = &DebugFrame::from(EndianSlice::default());
5039             let bases = &BaseAddresses::default();
5040             let mut table = match fde {
5041                 Some(fde) => UnwindTable::new_for_fde(section, bases, &mut initial_ctx, &fde),
5042                 None => UnwindTable::new_for_cie(section, bases, &mut initial_ctx, &cie),
5043             };
5044             for &(ref expected_result, ref instruction) in instructions.as_ref() {
5045                 assert_eq!(*expected_result, table.evaluate(instruction.clone()));
5046             }
5047         }
5048 
5049         assert_eq!(expected_ctx, initial_ctx);
5050     }
5051 
make_test_cie<'a>() -> CommonInformationEntry<EndianSlice<'a, LittleEndian>>5052     fn make_test_cie<'a>() -> CommonInformationEntry<EndianSlice<'a, LittleEndian>> {
5053         CommonInformationEntry {
5054             offset: 0,
5055             format: Format::Dwarf64,
5056             length: 0,
5057             return_address_register: Register(0),
5058             version: 4,
5059             address_size: mem::size_of::<usize>() as u8,
5060             initial_instructions: EndianSlice::new(&[], LittleEndian),
5061             augmentation: None,
5062             segment_size: 0,
5063             data_alignment_factor: 2,
5064             code_alignment_factor: 3,
5065         }
5066     }
5067 
5068     #[test]
test_eval_set_loc()5069     fn test_eval_set_loc() {
5070         let cie = make_test_cie();
5071         let ctx = UnwindContext::new();
5072         let mut expected = ctx.clone();
5073         expected.row_mut().end_address = 42;
5074         let instructions = [(Ok(true), CallFrameInstruction::SetLoc { address: 42 })];
5075         assert_eval(ctx, expected, cie, None, instructions);
5076     }
5077 
5078     #[test]
test_eval_set_loc_backwards()5079     fn test_eval_set_loc_backwards() {
5080         let cie = make_test_cie();
5081         let mut ctx = UnwindContext::new();
5082         ctx.row_mut().start_address = 999;
5083         let expected = ctx.clone();
5084         let instructions = [(
5085             Err(Error::InvalidAddressRange),
5086             CallFrameInstruction::SetLoc { address: 42 },
5087         )];
5088         assert_eval(ctx, expected, cie, None, instructions);
5089     }
5090 
5091     #[test]
test_eval_advance_loc()5092     fn test_eval_advance_loc() {
5093         let cie = make_test_cie();
5094         let mut ctx = UnwindContext::new();
5095         ctx.row_mut().start_address = 3;
5096         let mut expected = ctx.clone();
5097         expected.row_mut().end_address = 3 + 2 * cie.code_alignment_factor;
5098         let instructions = [(Ok(true), CallFrameInstruction::AdvanceLoc { delta: 2 })];
5099         assert_eval(ctx, expected, cie, None, instructions);
5100     }
5101 
5102     #[test]
test_eval_advance_loc_overflow()5103     fn test_eval_advance_loc_overflow() {
5104         let cie = make_test_cie();
5105         let mut ctx = UnwindContext::new();
5106         ctx.row_mut().start_address = u64::MAX;
5107         let mut expected = ctx.clone();
5108         expected.row_mut().end_address = 42 * cie.code_alignment_factor - 1;
5109         let instructions = [(Ok(true), CallFrameInstruction::AdvanceLoc { delta: 42 })];
5110         assert_eval(ctx, expected, cie, None, instructions);
5111     }
5112 
5113     #[test]
test_eval_def_cfa()5114     fn test_eval_def_cfa() {
5115         let cie = make_test_cie();
5116         let ctx = UnwindContext::new();
5117         let mut expected = ctx.clone();
5118         expected.set_cfa(CfaRule::RegisterAndOffset {
5119             register: Register(42),
5120             offset: 36,
5121         });
5122         let instructions = [(
5123             Ok(false),
5124             CallFrameInstruction::DefCfa {
5125                 register: Register(42),
5126                 offset: 36,
5127             },
5128         )];
5129         assert_eval(ctx, expected, cie, None, instructions);
5130     }
5131 
5132     #[test]
test_eval_def_cfa_sf()5133     fn test_eval_def_cfa_sf() {
5134         let cie = make_test_cie();
5135         let ctx = UnwindContext::new();
5136         let mut expected = ctx.clone();
5137         expected.set_cfa(CfaRule::RegisterAndOffset {
5138             register: Register(42),
5139             offset: 36 * cie.data_alignment_factor as i64,
5140         });
5141         let instructions = [(
5142             Ok(false),
5143             CallFrameInstruction::DefCfaSf {
5144                 register: Register(42),
5145                 factored_offset: 36,
5146             },
5147         )];
5148         assert_eval(ctx, expected, cie, None, instructions);
5149     }
5150 
5151     #[test]
test_eval_def_cfa_register()5152     fn test_eval_def_cfa_register() {
5153         let cie = make_test_cie();
5154         let mut ctx = UnwindContext::new();
5155         ctx.set_cfa(CfaRule::RegisterAndOffset {
5156             register: Register(3),
5157             offset: 8,
5158         });
5159         let mut expected = ctx.clone();
5160         expected.set_cfa(CfaRule::RegisterAndOffset {
5161             register: Register(42),
5162             offset: 8,
5163         });
5164         let instructions = [(
5165             Ok(false),
5166             CallFrameInstruction::DefCfaRegister {
5167                 register: Register(42),
5168             },
5169         )];
5170         assert_eval(ctx, expected, cie, None, instructions);
5171     }
5172 
5173     #[test]
test_eval_def_cfa_register_invalid_context()5174     fn test_eval_def_cfa_register_invalid_context() {
5175         let cie = make_test_cie();
5176         let mut ctx = UnwindContext::new();
5177         ctx.set_cfa(CfaRule::Expression(Expression(EndianSlice::new(
5178             &[],
5179             LittleEndian,
5180         ))));
5181         let expected = ctx.clone();
5182         let instructions = [(
5183             Err(Error::CfiInstructionInInvalidContext),
5184             CallFrameInstruction::DefCfaRegister {
5185                 register: Register(42),
5186             },
5187         )];
5188         assert_eval(ctx, expected, cie, None, instructions);
5189     }
5190 
5191     #[test]
test_eval_def_cfa_offset()5192     fn test_eval_def_cfa_offset() {
5193         let cie = make_test_cie();
5194         let mut ctx = UnwindContext::new();
5195         ctx.set_cfa(CfaRule::RegisterAndOffset {
5196             register: Register(3),
5197             offset: 8,
5198         });
5199         let mut expected = ctx.clone();
5200         expected.set_cfa(CfaRule::RegisterAndOffset {
5201             register: Register(3),
5202             offset: 42,
5203         });
5204         let instructions = [(Ok(false), CallFrameInstruction::DefCfaOffset { offset: 42 })];
5205         assert_eval(ctx, expected, cie, None, instructions);
5206     }
5207 
5208     #[test]
test_eval_def_cfa_offset_invalid_context()5209     fn test_eval_def_cfa_offset_invalid_context() {
5210         let cie = make_test_cie();
5211         let mut ctx = UnwindContext::new();
5212         ctx.set_cfa(CfaRule::Expression(Expression(EndianSlice::new(
5213             &[],
5214             LittleEndian,
5215         ))));
5216         let expected = ctx.clone();
5217         let instructions = [(
5218             Err(Error::CfiInstructionInInvalidContext),
5219             CallFrameInstruction::DefCfaOffset { offset: 1993 },
5220         )];
5221         assert_eval(ctx, expected, cie, None, instructions);
5222     }
5223 
5224     #[test]
test_eval_def_cfa_expression()5225     fn test_eval_def_cfa_expression() {
5226         let expr = [1, 2, 3, 4];
5227         let cie = make_test_cie();
5228         let ctx = UnwindContext::new();
5229         let mut expected = ctx.clone();
5230         expected.set_cfa(CfaRule::Expression(Expression(EndianSlice::new(
5231             &expr,
5232             LittleEndian,
5233         ))));
5234         let instructions = [(
5235             Ok(false),
5236             CallFrameInstruction::DefCfaExpression {
5237                 expression: Expression(EndianSlice::new(&expr, LittleEndian)),
5238             },
5239         )];
5240         assert_eval(ctx, expected, cie, None, instructions);
5241     }
5242 
5243     #[test]
test_eval_undefined()5244     fn test_eval_undefined() {
5245         let cie = make_test_cie();
5246         let ctx = UnwindContext::new();
5247         let mut expected = ctx.clone();
5248         expected
5249             .set_register_rule(Register(5), RegisterRule::Undefined)
5250             .unwrap();
5251         let instructions = [(
5252             Ok(false),
5253             CallFrameInstruction::Undefined {
5254                 register: Register(5),
5255             },
5256         )];
5257         assert_eval(ctx, expected, cie, None, instructions);
5258     }
5259 
5260     #[test]
test_eval_same_value()5261     fn test_eval_same_value() {
5262         let cie = make_test_cie();
5263         let ctx = UnwindContext::new();
5264         let mut expected = ctx.clone();
5265         expected
5266             .set_register_rule(Register(0), RegisterRule::SameValue)
5267             .unwrap();
5268         let instructions = [(
5269             Ok(false),
5270             CallFrameInstruction::SameValue {
5271                 register: Register(0),
5272             },
5273         )];
5274         assert_eval(ctx, expected, cie, None, instructions);
5275     }
5276 
5277     #[test]
test_eval_offset()5278     fn test_eval_offset() {
5279         let cie = make_test_cie();
5280         let ctx = UnwindContext::new();
5281         let mut expected = ctx.clone();
5282         expected
5283             .set_register_rule(
5284                 Register(2),
5285                 RegisterRule::Offset(3 * cie.data_alignment_factor),
5286             )
5287             .unwrap();
5288         let instructions = [(
5289             Ok(false),
5290             CallFrameInstruction::Offset {
5291                 register: Register(2),
5292                 factored_offset: 3,
5293             },
5294         )];
5295         assert_eval(ctx, expected, cie, None, instructions);
5296     }
5297 
5298     #[test]
test_eval_offset_extended_sf()5299     fn test_eval_offset_extended_sf() {
5300         let cie = make_test_cie();
5301         let ctx = UnwindContext::new();
5302         let mut expected = ctx.clone();
5303         expected
5304             .set_register_rule(
5305                 Register(4),
5306                 RegisterRule::Offset(-3 * cie.data_alignment_factor),
5307             )
5308             .unwrap();
5309         let instructions = [(
5310             Ok(false),
5311             CallFrameInstruction::OffsetExtendedSf {
5312                 register: Register(4),
5313                 factored_offset: -3,
5314             },
5315         )];
5316         assert_eval(ctx, expected, cie, None, instructions);
5317     }
5318 
5319     #[test]
test_eval_val_offset()5320     fn test_eval_val_offset() {
5321         let cie = make_test_cie();
5322         let ctx = UnwindContext::new();
5323         let mut expected = ctx.clone();
5324         expected
5325             .set_register_rule(
5326                 Register(5),
5327                 RegisterRule::ValOffset(7 * cie.data_alignment_factor),
5328             )
5329             .unwrap();
5330         let instructions = [(
5331             Ok(false),
5332             CallFrameInstruction::ValOffset {
5333                 register: Register(5),
5334                 factored_offset: 7,
5335             },
5336         )];
5337         assert_eval(ctx, expected, cie, None, instructions);
5338     }
5339 
5340     #[test]
test_eval_val_offset_sf()5341     fn test_eval_val_offset_sf() {
5342         let cie = make_test_cie();
5343         let ctx = UnwindContext::new();
5344         let mut expected = ctx.clone();
5345         expected
5346             .set_register_rule(
5347                 Register(5),
5348                 RegisterRule::ValOffset(-7 * cie.data_alignment_factor),
5349             )
5350             .unwrap();
5351         let instructions = [(
5352             Ok(false),
5353             CallFrameInstruction::ValOffsetSf {
5354                 register: Register(5),
5355                 factored_offset: -7,
5356             },
5357         )];
5358         assert_eval(ctx, expected, cie, None, instructions);
5359     }
5360 
5361     #[test]
test_eval_expression()5362     fn test_eval_expression() {
5363         let expr = [1, 2, 3, 4];
5364         let cie = make_test_cie();
5365         let ctx = UnwindContext::new();
5366         let mut expected = ctx.clone();
5367         expected
5368             .set_register_rule(
5369                 Register(9),
5370                 RegisterRule::Expression(Expression(EndianSlice::new(&expr, LittleEndian))),
5371             )
5372             .unwrap();
5373         let instructions = [(
5374             Ok(false),
5375             CallFrameInstruction::Expression {
5376                 register: Register(9),
5377                 expression: Expression(EndianSlice::new(&expr, LittleEndian)),
5378             },
5379         )];
5380         assert_eval(ctx, expected, cie, None, instructions);
5381     }
5382 
5383     #[test]
test_eval_val_expression()5384     fn test_eval_val_expression() {
5385         let expr = [1, 2, 3, 4];
5386         let cie = make_test_cie();
5387         let ctx = UnwindContext::new();
5388         let mut expected = ctx.clone();
5389         expected
5390             .set_register_rule(
5391                 Register(9),
5392                 RegisterRule::ValExpression(Expression(EndianSlice::new(&expr, LittleEndian))),
5393             )
5394             .unwrap();
5395         let instructions = [(
5396             Ok(false),
5397             CallFrameInstruction::ValExpression {
5398                 register: Register(9),
5399                 expression: Expression(EndianSlice::new(&expr, LittleEndian)),
5400             },
5401         )];
5402         assert_eval(ctx, expected, cie, None, instructions);
5403     }
5404 
5405     #[test]
test_eval_restore()5406     fn test_eval_restore() {
5407         let cie = make_test_cie();
5408         let fde = FrameDescriptionEntry {
5409             offset: 0,
5410             format: Format::Dwarf64,
5411             length: 0,
5412             address_range: 0,
5413             augmentation: None,
5414             initial_address: 0,
5415             initial_segment: 0,
5416             cie: cie.clone(),
5417             instructions: EndianSlice::new(&[], LittleEndian),
5418         };
5419 
5420         let mut ctx = UnwindContext::new();
5421         ctx.set_register_rule(Register(0), RegisterRule::Offset(1))
5422             .unwrap();
5423         ctx.save_initial_rules();
5424         let expected = ctx.clone();
5425         ctx.set_register_rule(Register(0), RegisterRule::Offset(2))
5426             .unwrap();
5427 
5428         let instructions = [(
5429             Ok(false),
5430             CallFrameInstruction::Restore {
5431                 register: Register(0),
5432             },
5433         )];
5434         assert_eval(ctx, expected, cie, Some(fde), instructions);
5435     }
5436 
5437     #[test]
test_eval_restore_havent_saved_initial_context()5438     fn test_eval_restore_havent_saved_initial_context() {
5439         let cie = make_test_cie();
5440         let ctx = UnwindContext::new();
5441         let expected = ctx.clone();
5442         let instructions = [(
5443             Err(Error::CfiInstructionInInvalidContext),
5444             CallFrameInstruction::Restore {
5445                 register: Register(0),
5446             },
5447         )];
5448         assert_eval(ctx, expected, cie, None, instructions);
5449     }
5450 
5451     #[test]
test_eval_remember_state()5452     fn test_eval_remember_state() {
5453         let cie = make_test_cie();
5454         let ctx = UnwindContext::new();
5455         let mut expected = ctx.clone();
5456         expected.push_row().unwrap();
5457         let instructions = [(Ok(false), CallFrameInstruction::RememberState)];
5458         assert_eval(ctx, expected, cie, None, instructions);
5459     }
5460 
5461     #[test]
test_eval_restore_state()5462     fn test_eval_restore_state() {
5463         let cie = make_test_cie();
5464 
5465         let mut ctx = UnwindContext::new();
5466         ctx.set_start_address(1);
5467         ctx.set_register_rule(Register(0), RegisterRule::SameValue)
5468             .unwrap();
5469         let mut expected = ctx.clone();
5470         ctx.push_row().unwrap();
5471         ctx.set_start_address(2);
5472         ctx.set_register_rule(Register(0), RegisterRule::Offset(16))
5473             .unwrap();
5474 
5475         // Restore state should preserve current location.
5476         expected.set_start_address(2);
5477 
5478         let instructions = [
5479             // First one pops just fine.
5480             (Ok(false), CallFrameInstruction::RestoreState),
5481             // Second pop would try to pop out of bounds.
5482             (
5483                 Err(Error::PopWithEmptyStack),
5484                 CallFrameInstruction::RestoreState,
5485             ),
5486         ];
5487 
5488         assert_eval(ctx, expected, cie, None, instructions);
5489     }
5490 
5491     #[test]
test_eval_nop()5492     fn test_eval_nop() {
5493         let cie = make_test_cie();
5494         let ctx = UnwindContext::new();
5495         let expected = ctx.clone();
5496         let instructions = [(Ok(false), CallFrameInstruction::Nop)];
5497         assert_eval(ctx, expected, cie, None, instructions);
5498     }
5499 
5500     #[test]
test_unwind_table_next_row()5501     fn test_unwind_table_next_row() {
5502         #[allow(clippy::identity_op)]
5503         let initial_instructions = Section::with_endian(Endian::Little)
5504             // The CFA is -12 from register 4.
5505             .D8(constants::DW_CFA_def_cfa_sf.0)
5506             .uleb(4)
5507             .sleb(-12)
5508             // Register 0 is 8 from the CFA.
5509             .D8(constants::DW_CFA_offset.0 | 0)
5510             .uleb(8)
5511             // Register 3 is 4 from the CFA.
5512             .D8(constants::DW_CFA_offset.0 | 3)
5513             .uleb(4)
5514             .append_repeated(constants::DW_CFA_nop.0, 4);
5515         let initial_instructions = initial_instructions.get_contents().unwrap();
5516 
5517         let cie = CommonInformationEntry {
5518             offset: 0,
5519             length: 0,
5520             format: Format::Dwarf32,
5521             version: 4,
5522             augmentation: None,
5523             address_size: 8,
5524             segment_size: 0,
5525             code_alignment_factor: 1,
5526             data_alignment_factor: 1,
5527             return_address_register: Register(3),
5528             initial_instructions: EndianSlice::new(&initial_instructions, LittleEndian),
5529         };
5530 
5531         let instructions = Section::with_endian(Endian::Little)
5532             // Initial instructions form a row, advance the address by 1.
5533             .D8(constants::DW_CFA_advance_loc1.0)
5534             .D8(1)
5535             // Register 0 is -16 from the CFA.
5536             .D8(constants::DW_CFA_offset_extended_sf.0)
5537             .uleb(0)
5538             .sleb(-16)
5539             // Finish this row, advance the address by 32.
5540             .D8(constants::DW_CFA_advance_loc1.0)
5541             .D8(32)
5542             // Register 3 is -4 from the CFA.
5543             .D8(constants::DW_CFA_offset_extended_sf.0)
5544             .uleb(3)
5545             .sleb(-4)
5546             // Finish this row, advance the address by 64.
5547             .D8(constants::DW_CFA_advance_loc1.0)
5548             .D8(64)
5549             // Register 5 is 4 from the CFA.
5550             .D8(constants::DW_CFA_offset.0 | 5)
5551             .uleb(4)
5552             // A bunch of nop padding.
5553             .append_repeated(constants::DW_CFA_nop.0, 8);
5554         let instructions = instructions.get_contents().unwrap();
5555 
5556         let fde = FrameDescriptionEntry {
5557             offset: 0,
5558             length: 0,
5559             format: Format::Dwarf32,
5560             cie: cie.clone(),
5561             initial_segment: 0,
5562             initial_address: 0,
5563             address_range: 100,
5564             augmentation: None,
5565             instructions: EndianSlice::new(&instructions, LittleEndian),
5566         };
5567 
5568         let section = &DebugFrame::from(EndianSlice::default());
5569         let bases = &BaseAddresses::default();
5570         let mut ctx = UninitializedUnwindContext::new();
5571         ctx.0.assert_fully_uninitialized();
5572 
5573         let mut table = fde
5574             .rows(section, bases, &mut ctx)
5575             .expect("Should run initial program OK");
5576         assert!(table.ctx.is_initialized);
5577         let expected_initial_rules: RegisterRuleMap<_> = [
5578             (Register(0), RegisterRule::Offset(8)),
5579             (Register(3), RegisterRule::Offset(4)),
5580         ]
5581         .iter()
5582         .collect();
5583         assert_eq!(table.ctx.initial_rules, expected_initial_rules);
5584 
5585         {
5586             let row = table.next_row().expect("Should evaluate first row OK");
5587             let expected = UnwindTableRow {
5588                 start_address: 0,
5589                 end_address: 1,
5590                 saved_args_size: 0,
5591                 cfa: CfaRule::RegisterAndOffset {
5592                     register: Register(4),
5593                     offset: -12,
5594                 },
5595                 registers: [
5596                     (Register(0), RegisterRule::Offset(8)),
5597                     (Register(3), RegisterRule::Offset(4)),
5598                 ]
5599                 .iter()
5600                 .collect(),
5601             };
5602             assert_eq!(Some(&expected), row);
5603         }
5604 
5605         {
5606             let row = table.next_row().expect("Should evaluate second row OK");
5607             let expected = UnwindTableRow {
5608                 start_address: 1,
5609                 end_address: 33,
5610                 saved_args_size: 0,
5611                 cfa: CfaRule::RegisterAndOffset {
5612                     register: Register(4),
5613                     offset: -12,
5614                 },
5615                 registers: [
5616                     (Register(0), RegisterRule::Offset(-16)),
5617                     (Register(3), RegisterRule::Offset(4)),
5618                 ]
5619                 .iter()
5620                 .collect(),
5621             };
5622             assert_eq!(Some(&expected), row);
5623         }
5624 
5625         {
5626             let row = table.next_row().expect("Should evaluate third row OK");
5627             let expected = UnwindTableRow {
5628                 start_address: 33,
5629                 end_address: 97,
5630                 saved_args_size: 0,
5631                 cfa: CfaRule::RegisterAndOffset {
5632                     register: Register(4),
5633                     offset: -12,
5634                 },
5635                 registers: [
5636                     (Register(0), RegisterRule::Offset(-16)),
5637                     (Register(3), RegisterRule::Offset(-4)),
5638                 ]
5639                 .iter()
5640                 .collect(),
5641             };
5642             assert_eq!(Some(&expected), row);
5643         }
5644 
5645         {
5646             let row = table.next_row().expect("Should evaluate fourth row OK");
5647             let expected = UnwindTableRow {
5648                 start_address: 97,
5649                 end_address: 100,
5650                 saved_args_size: 0,
5651                 cfa: CfaRule::RegisterAndOffset {
5652                     register: Register(4),
5653                     offset: -12,
5654                 },
5655                 registers: [
5656                     (Register(0), RegisterRule::Offset(-16)),
5657                     (Register(3), RegisterRule::Offset(-4)),
5658                     (Register(5), RegisterRule::Offset(4)),
5659                 ]
5660                 .iter()
5661                 .collect(),
5662             };
5663             assert_eq!(Some(&expected), row);
5664         }
5665 
5666         // All done!
5667         assert_eq!(Ok(None), table.next_row());
5668         assert_eq!(Ok(None), table.next_row());
5669     }
5670 
5671     #[test]
test_unwind_info_for_address_ok()5672     fn test_unwind_info_for_address_ok() {
5673         let instrs1 = Section::with_endian(Endian::Big)
5674             // The CFA is -12 from register 4.
5675             .D8(constants::DW_CFA_def_cfa_sf.0)
5676             .uleb(4)
5677             .sleb(-12);
5678         let instrs1 = instrs1.get_contents().unwrap();
5679 
5680         let instrs2: Vec<_> = (0..8).map(|_| constants::DW_CFA_nop.0).collect();
5681 
5682         let instrs3 = Section::with_endian(Endian::Big)
5683             // Initial instructions form a row, advance the address by 100.
5684             .D8(constants::DW_CFA_advance_loc1.0)
5685             .D8(100)
5686             // Register 0 is -16 from the CFA.
5687             .D8(constants::DW_CFA_offset_extended_sf.0)
5688             .uleb(0)
5689             .sleb(-16);
5690         let instrs3 = instrs3.get_contents().unwrap();
5691 
5692         let instrs4: Vec<_> = (0..16).map(|_| constants::DW_CFA_nop.0).collect();
5693 
5694         let mut cie1 = CommonInformationEntry {
5695             offset: 0,
5696             length: 0,
5697             format: Format::Dwarf32,
5698             version: 4,
5699             augmentation: None,
5700             address_size: 8,
5701             segment_size: 0,
5702             code_alignment_factor: 1,
5703             data_alignment_factor: 1,
5704             return_address_register: Register(3),
5705             initial_instructions: EndianSlice::new(&instrs1, BigEndian),
5706         };
5707 
5708         let mut cie2 = CommonInformationEntry {
5709             offset: 0,
5710             length: 0,
5711             format: Format::Dwarf32,
5712             version: 4,
5713             augmentation: None,
5714             address_size: 4,
5715             segment_size: 0,
5716             code_alignment_factor: 1,
5717             data_alignment_factor: 1,
5718             return_address_register: Register(1),
5719             initial_instructions: EndianSlice::new(&instrs2, BigEndian),
5720         };
5721 
5722         let cie1_location = Label::new();
5723         let cie2_location = Label::new();
5724 
5725         // Write the CIEs first so that their length gets set before we clone
5726         // them into the FDEs and our equality assertions down the line end up
5727         // with all the CIEs always having he correct length.
5728         let kind = debug_frame_be();
5729         let section = Section::with_endian(kind.endian())
5730             .mark(&cie1_location)
5731             .cie(kind, None, &mut cie1)
5732             .mark(&cie2_location)
5733             .cie(kind, None, &mut cie2);
5734 
5735         let mut fde1 = FrameDescriptionEntry {
5736             offset: 0,
5737             length: 0,
5738             format: Format::Dwarf32,
5739             cie: cie1.clone(),
5740             initial_segment: 0,
5741             initial_address: 0xfeed_beef,
5742             address_range: 200,
5743             augmentation: None,
5744             instructions: EndianSlice::new(&instrs3, BigEndian),
5745         };
5746 
5747         let mut fde2 = FrameDescriptionEntry {
5748             offset: 0,
5749             length: 0,
5750             format: Format::Dwarf32,
5751             cie: cie2.clone(),
5752             initial_segment: 0,
5753             initial_address: 0xfeed_face,
5754             address_range: 9000,
5755             augmentation: None,
5756             instructions: EndianSlice::new(&instrs4, BigEndian),
5757         };
5758 
5759         let section =
5760             section
5761                 .fde(kind, &cie1_location, &mut fde1)
5762                 .fde(kind, &cie2_location, &mut fde2);
5763         section.start().set_const(0);
5764 
5765         let contents = section.get_contents().unwrap();
5766         let debug_frame = kind.section(&contents);
5767 
5768         // Get the second row of the unwind table in `instrs3`.
5769         let bases = Default::default();
5770         let mut ctx = UninitializedUnwindContext::new();
5771         let result = debug_frame.unwind_info_for_address(
5772             &bases,
5773             &mut ctx,
5774             0xfeed_beef + 150,
5775             DebugFrame::cie_from_offset,
5776         );
5777         assert!(result.is_ok());
5778         let unwind_info = result.unwrap();
5779 
5780         assert_eq!(
5781             unwind_info,
5782             UnwindTableRow {
5783                 start_address: fde1.initial_address() + 100,
5784                 end_address: fde1.initial_address() + fde1.len(),
5785                 saved_args_size: 0,
5786                 cfa: CfaRule::RegisterAndOffset {
5787                     register: Register(4),
5788                     offset: -12,
5789                 },
5790                 registers: [(Register(0), RegisterRule::Offset(-16))].iter().collect(),
5791             }
5792         );
5793     }
5794 
5795     #[test]
test_unwind_info_for_address_not_found()5796     fn test_unwind_info_for_address_not_found() {
5797         let debug_frame = DebugFrame::new(&[], NativeEndian);
5798         let bases = Default::default();
5799         let mut ctx = UninitializedUnwindContext::new();
5800         let result = debug_frame.unwind_info_for_address(
5801             &bases,
5802             &mut ctx,
5803             0xbadb_ad99,
5804             DebugFrame::cie_from_offset,
5805         );
5806         assert!(result.is_err());
5807         assert_eq!(result.unwrap_err(), Error::NoUnwindInfoForAddress);
5808     }
5809 
5810     #[test]
test_eh_frame_hdr_unknown_version()5811     fn test_eh_frame_hdr_unknown_version() {
5812         let bases = BaseAddresses::default();
5813         let buf = &[42];
5814         let result = EhFrameHdr::new(buf, NativeEndian).parse(&bases, 8);
5815         assert!(result.is_err());
5816         assert_eq!(result.unwrap_err(), Error::UnknownVersion(42));
5817     }
5818 
5819     #[test]
test_eh_frame_hdr_omit_ehptr()5820     fn test_eh_frame_hdr_omit_ehptr() {
5821         let section = Section::with_endian(Endian::Little)
5822             .L8(1)
5823             .L8(0xff)
5824             .L8(0x03)
5825             .L8(0x0b)
5826             .L32(2)
5827             .L32(10)
5828             .L32(1)
5829             .L32(20)
5830             .L32(2)
5831             .L32(0);
5832         let section = section.get_contents().unwrap();
5833         let bases = BaseAddresses::default();
5834         let result = EhFrameHdr::new(&section, LittleEndian).parse(&bases, 8);
5835         assert!(result.is_err());
5836         assert_eq!(result.unwrap_err(), Error::CannotParseOmitPointerEncoding);
5837     }
5838 
5839     #[test]
test_eh_frame_hdr_omit_count()5840     fn test_eh_frame_hdr_omit_count() {
5841         let section = Section::with_endian(Endian::Little)
5842             .L8(1)
5843             .L8(0x0b)
5844             .L8(0xff)
5845             .L8(0x0b)
5846             .L32(0x12345);
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_ok());
5851         let result = result.unwrap();
5852         assert_eq!(result.eh_frame_ptr(), Pointer::Direct(0x12345));
5853         assert!(result.table().is_none());
5854     }
5855 
5856     #[test]
test_eh_frame_hdr_omit_table()5857     fn test_eh_frame_hdr_omit_table() {
5858         let section = Section::with_endian(Endian::Little)
5859             .L8(1)
5860             .L8(0x0b)
5861             .L8(0x03)
5862             .L8(0xff)
5863             .L32(0x12345)
5864             .L32(2);
5865         let section = section.get_contents().unwrap();
5866         let bases = BaseAddresses::default();
5867         let result = EhFrameHdr::new(&section, LittleEndian).parse(&bases, 8);
5868         assert!(result.is_ok());
5869         let result = result.unwrap();
5870         assert_eq!(result.eh_frame_ptr(), Pointer::Direct(0x12345));
5871         assert!(result.table().is_none());
5872     }
5873 
5874     #[test]
test_eh_frame_hdr_varlen_table()5875     fn test_eh_frame_hdr_varlen_table() {
5876         let section = Section::with_endian(Endian::Little)
5877             .L8(1)
5878             .L8(0x0b)
5879             .L8(0x03)
5880             .L8(0x01)
5881             .L32(0x12345)
5882             .L32(2);
5883         let section = section.get_contents().unwrap();
5884         let bases = BaseAddresses::default();
5885         let result = EhFrameHdr::new(&section, LittleEndian).parse(&bases, 8);
5886         assert!(result.is_ok());
5887         let result = result.unwrap();
5888         assert_eq!(result.eh_frame_ptr(), Pointer::Direct(0x12345));
5889         let table = result.table();
5890         assert!(table.is_some());
5891         let table = table.unwrap();
5892         assert_eq!(
5893             table.lookup(0, &bases),
5894             Err(Error::VariableLengthSearchTable)
5895         );
5896     }
5897 
5898     #[test]
test_eh_frame_hdr_indirect_length()5899     fn test_eh_frame_hdr_indirect_length() {
5900         let section = Section::with_endian(Endian::Little)
5901             .L8(1)
5902             .L8(0x0b)
5903             .L8(0x83)
5904             .L8(0x0b)
5905             .L32(0x12345)
5906             .L32(2);
5907         let section = section.get_contents().unwrap();
5908         let bases = BaseAddresses::default();
5909         let result = EhFrameHdr::new(&section, LittleEndian).parse(&bases, 8);
5910         assert!(result.is_err());
5911         assert_eq!(result.unwrap_err(), Error::UnsupportedPointerEncoding);
5912     }
5913 
5914     #[test]
test_eh_frame_hdr_indirect_ptrs()5915     fn test_eh_frame_hdr_indirect_ptrs() {
5916         let section = Section::with_endian(Endian::Little)
5917             .L8(1)
5918             .L8(0x8b)
5919             .L8(0x03)
5920             .L8(0x8b)
5921             .L32(0x12345)
5922             .L32(2)
5923             .L32(10)
5924             .L32(1)
5925             .L32(20)
5926             .L32(2);
5927         let section = section.get_contents().unwrap();
5928         let bases = BaseAddresses::default();
5929         let result = EhFrameHdr::new(&section, LittleEndian).parse(&bases, 8);
5930         assert!(result.is_ok());
5931         let result = result.unwrap();
5932         assert_eq!(result.eh_frame_ptr(), Pointer::Indirect(0x12345));
5933         let table = result.table();
5934         assert!(table.is_some());
5935         let table = table.unwrap();
5936         assert_eq!(
5937             table.lookup(0, &bases),
5938             Err(Error::UnsupportedPointerEncoding)
5939         );
5940     }
5941 
5942     #[test]
test_eh_frame_hdr_good()5943     fn test_eh_frame_hdr_good() {
5944         let section = Section::with_endian(Endian::Little)
5945             .L8(1)
5946             .L8(0x0b)
5947             .L8(0x03)
5948             .L8(0x0b)
5949             .L32(0x12345)
5950             .L32(2)
5951             .L32(10)
5952             .L32(1)
5953             .L32(20)
5954             .L32(2);
5955         let section = section.get_contents().unwrap();
5956         let bases = BaseAddresses::default();
5957         let result = EhFrameHdr::new(&section, LittleEndian).parse(&bases, 8);
5958         assert!(result.is_ok());
5959         let result = result.unwrap();
5960         assert_eq!(result.eh_frame_ptr(), Pointer::Direct(0x12345));
5961         let table = result.table();
5962         assert!(table.is_some());
5963         let table = table.unwrap();
5964         assert_eq!(table.lookup(0, &bases), Ok(Pointer::Direct(1)));
5965         assert_eq!(table.lookup(9, &bases), Ok(Pointer::Direct(1)));
5966         assert_eq!(table.lookup(10, &bases), Ok(Pointer::Direct(1)));
5967         assert_eq!(table.lookup(11, &bases), Ok(Pointer::Direct(1)));
5968         assert_eq!(table.lookup(19, &bases), Ok(Pointer::Direct(1)));
5969         assert_eq!(table.lookup(20, &bases), Ok(Pointer::Direct(2)));
5970         assert_eq!(table.lookup(21, &bases), Ok(Pointer::Direct(2)));
5971         assert_eq!(table.lookup(100_000, &bases), Ok(Pointer::Direct(2)));
5972     }
5973 
5974     #[test]
test_eh_frame_fde_for_address_good()5975     fn test_eh_frame_fde_for_address_good() {
5976         // First, setup eh_frame
5977         // Write the CIE first so that its length gets set before we clone it
5978         // into the FDE.
5979         let mut cie = make_test_cie();
5980         cie.format = Format::Dwarf32;
5981         cie.version = 1;
5982 
5983         let start_of_cie = Label::new();
5984         let end_of_cie = Label::new();
5985 
5986         let kind = eh_frame_le();
5987         let section = Section::with_endian(kind.endian())
5988             .append_repeated(0, 16)
5989             .mark(&start_of_cie)
5990             .cie(kind, None, &mut cie)
5991             .mark(&end_of_cie);
5992 
5993         let mut fde1 = FrameDescriptionEntry {
5994             offset: 0,
5995             length: 0,
5996             format: Format::Dwarf32,
5997             cie: cie.clone(),
5998             initial_segment: 0,
5999             initial_address: 9,
6000             address_range: 4,
6001             augmentation: None,
6002             instructions: EndianSlice::new(&[], LittleEndian),
6003         };
6004         let mut fde2 = FrameDescriptionEntry {
6005             offset: 0,
6006             length: 0,
6007             format: Format::Dwarf32,
6008             cie: cie.clone(),
6009             initial_segment: 0,
6010             initial_address: 20,
6011             address_range: 8,
6012             augmentation: None,
6013             instructions: EndianSlice::new(&[], LittleEndian),
6014         };
6015 
6016         let start_of_fde1 = Label::new();
6017         let start_of_fde2 = Label::new();
6018 
6019         let section = section
6020             // +4 for the FDE length before the CIE offset.
6021             .mark(&start_of_fde1)
6022             .fde(kind, (&start_of_fde1 - &start_of_cie + 4) as u64, &mut fde1)
6023             .mark(&start_of_fde2)
6024             .fde(kind, (&start_of_fde2 - &start_of_cie + 4) as u64, &mut fde2);
6025 
6026         section.start().set_const(0);
6027         let section = section.get_contents().unwrap();
6028         let section = EndianSlice::new(&section, LittleEndian);
6029         let eh_frame = kind.section(&section);
6030 
6031         // Setup eh_frame_hdr
6032         let section = Section::with_endian(kind.endian())
6033             .L8(1)
6034             .L8(0x0b)
6035             .L8(0x03)
6036             .L8(0x0b)
6037             .L32(0x12345)
6038             .L32(2)
6039             .L32(10)
6040             .L32(0x12345 + start_of_fde1.value().unwrap() as u32)
6041             .L32(20)
6042             .L32(0x12345 + start_of_fde2.value().unwrap() as u32);
6043 
6044         let section = section.get_contents().unwrap();
6045         let bases = BaseAddresses::default();
6046         let eh_frame_hdr = EhFrameHdr::new(&section, LittleEndian).parse(&bases, 8);
6047         assert!(eh_frame_hdr.is_ok());
6048         let eh_frame_hdr = eh_frame_hdr.unwrap();
6049 
6050         let table = eh_frame_hdr.table();
6051         assert!(table.is_some());
6052         let table = table.unwrap();
6053 
6054         let bases = Default::default();
6055 
6056         let f = |_: &_, _: &_, o: EhFrameOffset| {
6057             assert_eq!(o, EhFrameOffset(start_of_cie.value().unwrap() as usize));
6058             Ok(cie.clone())
6059         };
6060         assert_eq!(
6061             table.fde_for_address(&eh_frame, &bases, 9, f),
6062             Ok(fde1.clone())
6063         );
6064         assert_eq!(
6065             table.fde_for_address(&eh_frame, &bases, 10, f),
6066             Ok(fde1.clone())
6067         );
6068         assert_eq!(table.fde_for_address(&eh_frame, &bases, 11, f), Ok(fde1));
6069         assert_eq!(
6070             table.fde_for_address(&eh_frame, &bases, 19, f),
6071             Err(Error::NoUnwindInfoForAddress)
6072         );
6073         assert_eq!(
6074             table.fde_for_address(&eh_frame, &bases, 20, f),
6075             Ok(fde2.clone())
6076         );
6077         assert_eq!(table.fde_for_address(&eh_frame, &bases, 21, f), Ok(fde2));
6078         assert_eq!(
6079             table.fde_for_address(&eh_frame, &bases, 100_000, f),
6080             Err(Error::NoUnwindInfoForAddress)
6081         );
6082     }
6083 
6084     #[test]
test_eh_frame_stops_at_zero_length()6085     fn test_eh_frame_stops_at_zero_length() {
6086         let section = Section::with_endian(Endian::Little).L32(0);
6087         let section = section.get_contents().unwrap();
6088         let rest = &mut EndianSlice::new(&section, LittleEndian);
6089         let bases = Default::default();
6090 
6091         assert_eq!(
6092             parse_cfi_entry(&bases, &EhFrame::new(&*section, LittleEndian), rest),
6093             Ok(None)
6094         );
6095 
6096         assert_eq!(
6097             EhFrame::new(&section, LittleEndian).cie_from_offset(&bases, EhFrameOffset(0)),
6098             Err(Error::NoEntryAtGivenOffset)
6099         );
6100     }
6101 
resolve_cie_offset(buf: &[u8], cie_offset: usize) -> Result<usize>6102     fn resolve_cie_offset(buf: &[u8], cie_offset: usize) -> Result<usize> {
6103         let mut fde = FrameDescriptionEntry {
6104             offset: 0,
6105             length: 0,
6106             format: Format::Dwarf64,
6107             cie: make_test_cie(),
6108             initial_segment: 0,
6109             initial_address: 0xfeed_beef,
6110             address_range: 39,
6111             augmentation: None,
6112             instructions: EndianSlice::new(&[], LittleEndian),
6113         };
6114 
6115         let kind = eh_frame_le();
6116         let section = Section::with_endian(kind.endian())
6117             .append_bytes(&buf)
6118             .fde(kind, cie_offset as u64, &mut fde)
6119             .append_bytes(&buf);
6120 
6121         let section = section.get_contents().unwrap();
6122         let eh_frame = kind.section(&section);
6123         let input = &mut EndianSlice::new(&section[buf.len()..], LittleEndian);
6124 
6125         let bases = Default::default();
6126         match parse_cfi_entry(&bases, &eh_frame, input) {
6127             Ok(Some(CieOrFde::Fde(partial))) => Ok(partial.cie_offset.0),
6128             Err(e) => Err(e),
6129             otherwise => panic!("Unexpected result: {:#?}", otherwise),
6130         }
6131     }
6132 
6133     #[test]
test_eh_frame_resolve_cie_offset_ok()6134     fn test_eh_frame_resolve_cie_offset_ok() {
6135         let buf = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
6136         let cie_offset = 2;
6137         // + 4 for size of length field
6138         assert_eq!(
6139             resolve_cie_offset(&buf, buf.len() + 4 - cie_offset),
6140             Ok(cie_offset)
6141         );
6142     }
6143 
6144     #[test]
test_eh_frame_resolve_cie_offset_out_of_bounds()6145     fn test_eh_frame_resolve_cie_offset_out_of_bounds() {
6146         let buf = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
6147         assert_eq!(
6148             resolve_cie_offset(&buf, buf.len() + 4 + 2),
6149             Err(Error::OffsetOutOfBounds)
6150         );
6151     }
6152 
6153     #[test]
test_eh_frame_resolve_cie_offset_underflow()6154     fn test_eh_frame_resolve_cie_offset_underflow() {
6155         let buf = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
6156         assert_eq!(
6157             resolve_cie_offset(&buf, ::core::usize::MAX),
6158             Err(Error::OffsetOutOfBounds)
6159         );
6160     }
6161 
6162     #[test]
test_eh_frame_fde_ok()6163     fn test_eh_frame_fde_ok() {
6164         let mut cie = make_test_cie();
6165         cie.format = Format::Dwarf32;
6166         cie.version = 1;
6167 
6168         let start_of_cie = Label::new();
6169         let end_of_cie = Label::new();
6170 
6171         // Write the CIE first so that its length gets set before we clone it
6172         // into the FDE.
6173         let kind = eh_frame_le();
6174         let section = Section::with_endian(kind.endian())
6175             .append_repeated(0, 16)
6176             .mark(&start_of_cie)
6177             .cie(kind, None, &mut cie)
6178             .mark(&end_of_cie);
6179 
6180         let mut fde = FrameDescriptionEntry {
6181             offset: 0,
6182             length: 0,
6183             format: Format::Dwarf32,
6184             cie: cie.clone(),
6185             initial_segment: 0,
6186             initial_address: 0xfeed_beef,
6187             address_range: 999,
6188             augmentation: None,
6189             instructions: EndianSlice::new(&[], LittleEndian),
6190         };
6191 
6192         let section = section
6193             // +4 for the FDE length before the CIE offset.
6194             .fde(kind, (&end_of_cie - &start_of_cie + 4) as u64, &mut fde);
6195 
6196         section.start().set_const(0);
6197         let section = section.get_contents().unwrap();
6198         let eh_frame = kind.section(&section);
6199         let section = EndianSlice::new(&section, LittleEndian);
6200 
6201         let mut offset = None;
6202         match parse_fde(
6203             eh_frame,
6204             &mut section.range_from(end_of_cie.value().unwrap() as usize..),
6205             |_, _, o| {
6206                 offset = Some(o);
6207                 assert_eq!(o, EhFrameOffset(start_of_cie.value().unwrap() as usize));
6208                 Ok(cie.clone())
6209             },
6210         ) {
6211             Ok(actual) => assert_eq!(actual, fde),
6212             otherwise => panic!("Unexpected result {:?}", otherwise),
6213         }
6214         assert!(offset.is_some());
6215     }
6216 
6217     #[test]
test_eh_frame_fde_out_of_bounds()6218     fn test_eh_frame_fde_out_of_bounds() {
6219         let mut cie = make_test_cie();
6220         cie.version = 1;
6221 
6222         let end_of_cie = Label::new();
6223 
6224         let mut fde = FrameDescriptionEntry {
6225             offset: 0,
6226             length: 0,
6227             format: Format::Dwarf64,
6228             cie: cie.clone(),
6229             initial_segment: 0,
6230             initial_address: 0xfeed_beef,
6231             address_range: 999,
6232             augmentation: None,
6233             instructions: EndianSlice::new(&[], LittleEndian),
6234         };
6235 
6236         let kind = eh_frame_le();
6237         let section = Section::with_endian(kind.endian())
6238             .cie(kind, None, &mut cie)
6239             .mark(&end_of_cie)
6240             .fde(kind, 99_999_999_999_999, &mut fde);
6241 
6242         section.start().set_const(0);
6243         let section = section.get_contents().unwrap();
6244         let eh_frame = kind.section(&section);
6245         let section = EndianSlice::new(&section, LittleEndian);
6246 
6247         let result = parse_fde(
6248             eh_frame,
6249             &mut section.range_from(end_of_cie.value().unwrap() as usize..),
6250             UnwindSection::cie_from_offset,
6251         );
6252         assert_eq!(result, Err(Error::OffsetOutOfBounds));
6253     }
6254 
6255     #[test]
test_augmentation_parse_not_z_augmentation()6256     fn test_augmentation_parse_not_z_augmentation() {
6257         let augmentation = &mut EndianSlice::new(b"wtf", NativeEndian);
6258         let bases = Default::default();
6259         let address_size = 8;
6260         let section = EhFrame::new(&[], NativeEndian);
6261         let input = &mut EndianSlice::new(&[], NativeEndian);
6262         assert_eq!(
6263             Augmentation::parse(augmentation, &bases, address_size, &section, input),
6264             Err(Error::UnknownAugmentation)
6265         );
6266     }
6267 
6268     #[test]
test_augmentation_parse_just_signal_trampoline()6269     fn test_augmentation_parse_just_signal_trampoline() {
6270         let aug_str = &mut EndianSlice::new(b"S", LittleEndian);
6271         let bases = Default::default();
6272         let address_size = 8;
6273         let section = EhFrame::new(&[], LittleEndian);
6274         let input = &mut EndianSlice::new(&[], LittleEndian);
6275 
6276         let mut augmentation = Augmentation::default();
6277         augmentation.is_signal_trampoline = true;
6278 
6279         assert_eq!(
6280             Augmentation::parse(aug_str, &bases, address_size, &section, input),
6281             Ok(augmentation)
6282         );
6283     }
6284 
6285     #[test]
test_augmentation_parse_unknown_part_of_z_augmentation()6286     fn test_augmentation_parse_unknown_part_of_z_augmentation() {
6287         // The 'Z' character is not defined by the z-style augmentation.
6288         let bases = Default::default();
6289         let address_size = 8;
6290         let section = Section::with_endian(Endian::Little)
6291             .uleb(4)
6292             .append_repeated(4, 4)
6293             .get_contents()
6294             .unwrap();
6295         let section = EhFrame::new(&section, LittleEndian);
6296         let input = &mut section.section().clone();
6297         let augmentation = &mut EndianSlice::new(b"zZ", LittleEndian);
6298         assert_eq!(
6299             Augmentation::parse(augmentation, &bases, address_size, &section, input),
6300             Err(Error::UnknownAugmentation)
6301         );
6302     }
6303 
6304     #[test]
6305     #[allow(non_snake_case)]
test_augmentation_parse_L()6306     fn test_augmentation_parse_L() {
6307         let bases = Default::default();
6308         let address_size = 8;
6309         let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1];
6310 
6311         let section = Section::with_endian(Endian::Little)
6312             .uleb(1)
6313             .D8(constants::DW_EH_PE_uleb128.0)
6314             .append_bytes(&rest)
6315             .get_contents()
6316             .unwrap();
6317         let section = EhFrame::new(&section, LittleEndian);
6318         let input = &mut section.section().clone();
6319         let aug_str = &mut EndianSlice::new(b"zL", LittleEndian);
6320 
6321         let mut augmentation = Augmentation::default();
6322         augmentation.lsda = Some(constants::DW_EH_PE_uleb128);
6323 
6324         assert_eq!(
6325             Augmentation::parse(aug_str, &bases, address_size, &section, input),
6326             Ok(augmentation)
6327         );
6328         assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
6329     }
6330 
6331     #[test]
6332     #[allow(non_snake_case)]
test_augmentation_parse_P()6333     fn test_augmentation_parse_P() {
6334         let bases = Default::default();
6335         let address_size = 8;
6336         let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1];
6337 
6338         let section = Section::with_endian(Endian::Little)
6339             .uleb(9)
6340             .D8(constants::DW_EH_PE_udata8.0)
6341             .L64(0xf00d_f00d)
6342             .append_bytes(&rest)
6343             .get_contents()
6344             .unwrap();
6345         let section = EhFrame::new(&section, LittleEndian);
6346         let input = &mut section.section().clone();
6347         let aug_str = &mut EndianSlice::new(b"zP", LittleEndian);
6348 
6349         let mut augmentation = Augmentation::default();
6350         augmentation.personality = Some((constants::DW_EH_PE_udata8, Pointer::Direct(0xf00d_f00d)));
6351 
6352         assert_eq!(
6353             Augmentation::parse(aug_str, &bases, address_size, &section, input),
6354             Ok(augmentation)
6355         );
6356         assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
6357     }
6358 
6359     #[test]
6360     #[allow(non_snake_case)]
test_augmentation_parse_R()6361     fn test_augmentation_parse_R() {
6362         let bases = Default::default();
6363         let address_size = 8;
6364         let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1];
6365 
6366         let section = Section::with_endian(Endian::Little)
6367             .uleb(1)
6368             .D8(constants::DW_EH_PE_udata4.0)
6369             .append_bytes(&rest)
6370             .get_contents()
6371             .unwrap();
6372         let section = EhFrame::new(&section, LittleEndian);
6373         let input = &mut section.section().clone();
6374         let aug_str = &mut EndianSlice::new(b"zR", LittleEndian);
6375 
6376         let mut augmentation = Augmentation::default();
6377         augmentation.fde_address_encoding = Some(constants::DW_EH_PE_udata4);
6378 
6379         assert_eq!(
6380             Augmentation::parse(aug_str, &bases, address_size, &section, input),
6381             Ok(augmentation)
6382         );
6383         assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
6384     }
6385 
6386     #[test]
6387     #[allow(non_snake_case)]
test_augmentation_parse_S()6388     fn test_augmentation_parse_S() {
6389         let bases = Default::default();
6390         let address_size = 8;
6391         let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1];
6392 
6393         let section = Section::with_endian(Endian::Little)
6394             .uleb(0)
6395             .append_bytes(&rest)
6396             .get_contents()
6397             .unwrap();
6398         let section = EhFrame::new(&section, LittleEndian);
6399         let input = &mut section.section().clone();
6400         let aug_str = &mut EndianSlice::new(b"zS", LittleEndian);
6401 
6402         let mut augmentation = Augmentation::default();
6403         augmentation.is_signal_trampoline = true;
6404 
6405         assert_eq!(
6406             Augmentation::parse(aug_str, &bases, address_size, &section, input),
6407             Ok(augmentation)
6408         );
6409         assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
6410     }
6411 
6412     #[test]
test_augmentation_parse_all()6413     fn test_augmentation_parse_all() {
6414         let bases = Default::default();
6415         let address_size = 8;
6416         let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1];
6417 
6418         let section = Section::with_endian(Endian::Little)
6419             .uleb(1 + 9 + 1)
6420             // L
6421             .D8(constants::DW_EH_PE_uleb128.0)
6422             // P
6423             .D8(constants::DW_EH_PE_udata8.0)
6424             .L64(0x1bad_f00d)
6425             // R
6426             .D8(constants::DW_EH_PE_uleb128.0)
6427             .append_bytes(&rest)
6428             .get_contents()
6429             .unwrap();
6430         let section = EhFrame::new(&section, LittleEndian);
6431         let input = &mut section.section().clone();
6432         let aug_str = &mut EndianSlice::new(b"zLPRS", LittleEndian);
6433 
6434         let augmentation = Augmentation {
6435             lsda: Some(constants::DW_EH_PE_uleb128),
6436             personality: Some((constants::DW_EH_PE_udata8, Pointer::Direct(0x1bad_f00d))),
6437             fde_address_encoding: Some(constants::DW_EH_PE_uleb128),
6438             is_signal_trampoline: true,
6439         };
6440 
6441         assert_eq!(
6442             Augmentation::parse(aug_str, &bases, address_size, &section, input),
6443             Ok(augmentation)
6444         );
6445         assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
6446     }
6447 
6448     #[test]
test_eh_frame_fde_no_augmentation()6449     fn test_eh_frame_fde_no_augmentation() {
6450         let instrs = [1, 2, 3, 4];
6451         let cie_offset = 1;
6452 
6453         let mut cie = make_test_cie();
6454         cie.format = Format::Dwarf32;
6455         cie.version = 1;
6456 
6457         let mut fde = FrameDescriptionEntry {
6458             offset: 0,
6459             length: 0,
6460             format: Format::Dwarf32,
6461             cie: cie.clone(),
6462             initial_segment: 0,
6463             initial_address: 0xfeed_face,
6464             address_range: 9000,
6465             augmentation: None,
6466             instructions: EndianSlice::new(&instrs, LittleEndian),
6467         };
6468 
6469         let rest = [1, 2, 3, 4];
6470 
6471         let kind = eh_frame_le();
6472         let section = Section::with_endian(kind.endian())
6473             .fde(kind, cie_offset, &mut fde)
6474             .append_bytes(&rest)
6475             .get_contents()
6476             .unwrap();
6477         let section = kind.section(&section);
6478         let input = &mut section.section().clone();
6479 
6480         let result = parse_fde(section, input, |_, _, _| Ok(cie.clone()));
6481         assert_eq!(result, Ok(fde));
6482         assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
6483     }
6484 
6485     #[test]
test_eh_frame_fde_empty_augmentation()6486     fn test_eh_frame_fde_empty_augmentation() {
6487         let instrs = [1, 2, 3, 4];
6488         let cie_offset = 1;
6489 
6490         let mut cie = make_test_cie();
6491         cie.format = Format::Dwarf32;
6492         cie.version = 1;
6493         cie.augmentation = Some(Augmentation::default());
6494 
6495         let mut fde = FrameDescriptionEntry {
6496             offset: 0,
6497             length: 0,
6498             format: Format::Dwarf32,
6499             cie: cie.clone(),
6500             initial_segment: 0,
6501             initial_address: 0xfeed_face,
6502             address_range: 9000,
6503             augmentation: Some(AugmentationData::default()),
6504             instructions: EndianSlice::new(&instrs, LittleEndian),
6505         };
6506 
6507         let rest = [1, 2, 3, 4];
6508 
6509         let kind = eh_frame_le();
6510         let section = Section::with_endian(kind.endian())
6511             .fde(kind, cie_offset, &mut fde)
6512             .append_bytes(&rest)
6513             .get_contents()
6514             .unwrap();
6515         let section = kind.section(&section);
6516         let input = &mut section.section().clone();
6517 
6518         let result = parse_fde(section, input, |_, _, _| Ok(cie.clone()));
6519         assert_eq!(result, Ok(fde));
6520         assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
6521     }
6522 
6523     #[test]
test_eh_frame_fde_lsda_augmentation()6524     fn test_eh_frame_fde_lsda_augmentation() {
6525         let instrs = [1, 2, 3, 4];
6526         let cie_offset = 1;
6527 
6528         let mut cie = make_test_cie();
6529         cie.format = Format::Dwarf32;
6530         cie.version = 1;
6531         cie.augmentation = Some(Augmentation::default());
6532         cie.augmentation.as_mut().unwrap().lsda = Some(constants::DW_EH_PE_absptr);
6533 
6534         let mut fde = FrameDescriptionEntry {
6535             offset: 0,
6536             length: 0,
6537             format: Format::Dwarf32,
6538             cie: cie.clone(),
6539             initial_segment: 0,
6540             initial_address: 0xfeed_face,
6541             address_range: 9000,
6542             augmentation: Some(AugmentationData {
6543                 lsda: Some(Pointer::Direct(0x1122_3344)),
6544             }),
6545             instructions: EndianSlice::new(&instrs, LittleEndian),
6546         };
6547 
6548         let rest = [1, 2, 3, 4];
6549 
6550         let kind = eh_frame_le();
6551         let section = Section::with_endian(kind.endian())
6552             .fde(kind, cie_offset, &mut fde)
6553             .append_bytes(&rest)
6554             .get_contents()
6555             .unwrap();
6556         let section = kind.section(&section);
6557         let input = &mut section.section().clone();
6558 
6559         let result = parse_fde(section, input, |_, _, _| Ok(cie.clone()));
6560         assert_eq!(result, Ok(fde));
6561         assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
6562     }
6563 
6564     #[test]
test_eh_frame_fde_lsda_function_relative()6565     fn test_eh_frame_fde_lsda_function_relative() {
6566         let instrs = [1, 2, 3, 4];
6567         let cie_offset = 1;
6568 
6569         let mut cie = make_test_cie();
6570         cie.format = Format::Dwarf32;
6571         cie.version = 1;
6572         cie.augmentation = Some(Augmentation::default());
6573         cie.augmentation.as_mut().unwrap().lsda = Some(constants::DwEhPe(
6574             constants::DW_EH_PE_funcrel.0 | constants::DW_EH_PE_absptr.0,
6575         ));
6576 
6577         let mut fde = FrameDescriptionEntry {
6578             offset: 0,
6579             length: 0,
6580             format: Format::Dwarf32,
6581             cie: cie.clone(),
6582             initial_segment: 0,
6583             initial_address: 0xfeed_face,
6584             address_range: 9000,
6585             augmentation: Some(AugmentationData {
6586                 lsda: Some(Pointer::Direct(0xbeef)),
6587             }),
6588             instructions: EndianSlice::new(&instrs, LittleEndian),
6589         };
6590 
6591         let rest = [1, 2, 3, 4];
6592 
6593         let kind = eh_frame_le();
6594         let section = Section::with_endian(kind.endian())
6595             .append_repeated(10, 10)
6596             .fde(kind, cie_offset, &mut fde)
6597             .append_bytes(&rest)
6598             .get_contents()
6599             .unwrap();
6600         let section = kind.section(&section);
6601         let input = &mut section.section().range_from(10..);
6602 
6603         // Adjust the FDE's augmentation to be relative to the function.
6604         fde.augmentation.as_mut().unwrap().lsda = Some(Pointer::Direct(0xfeed_face + 0xbeef));
6605 
6606         let result = parse_fde(section, input, |_, _, _| Ok(cie.clone()));
6607         assert_eq!(result, Ok(fde));
6608         assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
6609     }
6610 
6611     #[test]
test_eh_frame_cie_personality_function_relative_bad_context()6612     fn test_eh_frame_cie_personality_function_relative_bad_context() {
6613         let instrs = [1, 2, 3, 4];
6614 
6615         let length = Label::new();
6616         let start = Label::new();
6617         let end = Label::new();
6618 
6619         let aug_len = Label::new();
6620         let aug_start = Label::new();
6621         let aug_end = Label::new();
6622 
6623         let section = Section::with_endian(Endian::Little)
6624             // Length
6625             .L32(&length)
6626             .mark(&start)
6627             // CIE ID
6628             .L32(0)
6629             // Version
6630             .D8(1)
6631             // Augmentation
6632             .append_bytes(b"zP\0")
6633             // Code alignment factor
6634             .uleb(1)
6635             // Data alignment factor
6636             .sleb(1)
6637             // Return address register
6638             .uleb(1)
6639             // Augmentation data length. This is a uleb, be we rely on the value
6640             // being less than 2^7 and therefore a valid uleb (can't use Label
6641             // with uleb).
6642             .D8(&aug_len)
6643             .mark(&aug_start)
6644             // Augmentation data. Personality encoding and then encoded pointer.
6645             .D8(constants::DW_EH_PE_funcrel.0 | constants::DW_EH_PE_uleb128.0)
6646             .uleb(1)
6647             .mark(&aug_end)
6648             // Initial instructions
6649             .append_bytes(&instrs)
6650             .mark(&end);
6651 
6652         length.set_const((&end - &start) as u64);
6653         aug_len.set_const((&aug_end - &aug_start) as u64);
6654 
6655         let section = section.get_contents().unwrap();
6656         let section = EhFrame::new(&section, LittleEndian);
6657 
6658         let bases = BaseAddresses::default();
6659         let mut iter = section.entries(&bases);
6660         assert_eq!(iter.next(), Err(Error::FuncRelativePointerInBadContext));
6661     }
6662 
6663     #[test]
register_rule_map_eq()6664     fn register_rule_map_eq() {
6665         // Different order, but still equal.
6666         let map1: RegisterRuleMap<EndianSlice<LittleEndian>> = [
6667             (Register(0), RegisterRule::SameValue),
6668             (Register(3), RegisterRule::Offset(1)),
6669         ]
6670         .iter()
6671         .collect();
6672         let map2: RegisterRuleMap<EndianSlice<LittleEndian>> = [
6673             (Register(3), RegisterRule::Offset(1)),
6674             (Register(0), RegisterRule::SameValue),
6675         ]
6676         .iter()
6677         .collect();
6678         assert_eq!(map1, map2);
6679         assert_eq!(map2, map1);
6680 
6681         // Not equal.
6682         let map3: RegisterRuleMap<EndianSlice<LittleEndian>> = [
6683             (Register(0), RegisterRule::SameValue),
6684             (Register(2), RegisterRule::Offset(1)),
6685         ]
6686         .iter()
6687         .collect();
6688         let map4: RegisterRuleMap<EndianSlice<LittleEndian>> = [
6689             (Register(3), RegisterRule::Offset(1)),
6690             (Register(0), RegisterRule::SameValue),
6691         ]
6692         .iter()
6693         .collect();
6694         assert!(map3 != map4);
6695         assert!(map4 != map3);
6696 
6697         // One has undefined explicitly set, other implicitly has undefined.
6698         let mut map5 = RegisterRuleMap::<EndianSlice<LittleEndian>>::default();
6699         map5.set(Register(0), RegisterRule::SameValue).unwrap();
6700         map5.set(Register(0), RegisterRule::Undefined).unwrap();
6701         let map6 = RegisterRuleMap::<EndianSlice<LittleEndian>>::default();
6702         assert_eq!(map5, map6);
6703         assert_eq!(map6, map5);
6704     }
6705 
6706     #[test]
iter_register_rules()6707     fn iter_register_rules() {
6708         let mut row = UnwindTableRow::<EndianSlice<LittleEndian>>::default();
6709         row.registers = [
6710             (Register(0), RegisterRule::SameValue),
6711             (Register(1), RegisterRule::Offset(1)),
6712             (Register(2), RegisterRule::ValOffset(2)),
6713         ]
6714         .iter()
6715         .collect();
6716 
6717         let mut found0 = false;
6718         let mut found1 = false;
6719         let mut found2 = false;
6720 
6721         for &(register, ref rule) in row.registers() {
6722             match register.0 {
6723                 0 => {
6724                     assert_eq!(found0, false);
6725                     found0 = true;
6726                     assert_eq!(*rule, RegisterRule::SameValue);
6727                 }
6728                 1 => {
6729                     assert_eq!(found1, false);
6730                     found1 = true;
6731                     assert_eq!(*rule, RegisterRule::Offset(1));
6732                 }
6733                 2 => {
6734                     assert_eq!(found2, false);
6735                     found2 = true;
6736                     assert_eq!(*rule, RegisterRule::ValOffset(2));
6737                 }
6738                 x => panic!("Unexpected register rule: ({}, {:?})", x, rule),
6739             }
6740         }
6741 
6742         assert_eq!(found0, true);
6743         assert_eq!(found1, true);
6744         assert_eq!(found2, true);
6745     }
6746 
6747     #[test]
6748     #[cfg(target_pointer_width = "64")]
size_of_unwind_ctx()6749     fn size_of_unwind_ctx() {
6750         use core::mem;
6751         let size = mem::size_of::<UnwindContext<EndianSlice<NativeEndian>>>();
6752         let max_size = 30968;
6753         if size > max_size {
6754             assert_eq!(size, max_size);
6755         }
6756     }
6757 
6758     #[test]
6759     #[cfg(target_pointer_width = "64")]
size_of_register_rule_map()6760     fn size_of_register_rule_map() {
6761         use core::mem;
6762         let size = mem::size_of::<RegisterRuleMap<EndianSlice<NativeEndian>>>();
6763         let max_size = 6152;
6764         if size > max_size {
6765             assert_eq!(size, max_size);
6766         }
6767     }
6768 
6769     #[test]
test_parse_pointer_encoding_ok()6770     fn test_parse_pointer_encoding_ok() {
6771         use crate::endianity::NativeEndian;
6772         let expected =
6773             constants::DwEhPe(constants::DW_EH_PE_uleb128.0 | constants::DW_EH_PE_pcrel.0);
6774         let input = [expected.0, 1, 2, 3, 4];
6775         let input = &mut EndianSlice::new(&input, NativeEndian);
6776         assert_eq!(parse_pointer_encoding(input), Ok(expected));
6777         assert_eq!(*input, EndianSlice::new(&[1, 2, 3, 4], NativeEndian));
6778     }
6779 
6780     #[test]
test_parse_pointer_encoding_bad_encoding()6781     fn test_parse_pointer_encoding_bad_encoding() {
6782         use crate::endianity::NativeEndian;
6783         let expected =
6784             constants::DwEhPe((constants::DW_EH_PE_sdata8.0 + 1) | constants::DW_EH_PE_pcrel.0);
6785         let input = [expected.0, 1, 2, 3, 4];
6786         let input = &mut EndianSlice::new(&input, NativeEndian);
6787         assert_eq!(
6788             Err(Error::UnknownPointerEncoding),
6789             parse_pointer_encoding(input)
6790         );
6791     }
6792 
6793     #[test]
test_parse_encoded_pointer_absptr()6794     fn test_parse_encoded_pointer_absptr() {
6795         let encoding = constants::DW_EH_PE_absptr;
6796         let expected_rest = [1, 2, 3, 4];
6797 
6798         let input = Section::with_endian(Endian::Little)
6799             .L32(0xf00d_f00d)
6800             .append_bytes(&expected_rest);
6801         let input = input.get_contents().unwrap();
6802         let input = EndianSlice::new(&input, LittleEndian);
6803         let mut rest = input;
6804 
6805         let parameters = PointerEncodingParameters {
6806             bases: &SectionBaseAddresses::default(),
6807             func_base: None,
6808             address_size: 4,
6809             section: &input,
6810         };
6811         assert_eq!(
6812             parse_encoded_pointer(encoding, &parameters, &mut rest),
6813             Ok(Pointer::Direct(0xf00d_f00d))
6814         );
6815         assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
6816     }
6817 
6818     #[test]
test_parse_encoded_pointer_pcrel()6819     fn test_parse_encoded_pointer_pcrel() {
6820         let encoding = constants::DW_EH_PE_pcrel;
6821         let expected_rest = [1, 2, 3, 4];
6822 
6823         let input = Section::with_endian(Endian::Little)
6824             .append_repeated(0, 0x10)
6825             .L32(0x1)
6826             .append_bytes(&expected_rest);
6827         let input = input.get_contents().unwrap();
6828         let input = EndianSlice::new(&input, LittleEndian);
6829         let mut rest = input.range_from(0x10..);
6830 
6831         let parameters = PointerEncodingParameters {
6832             bases: &BaseAddresses::default().set_eh_frame(0x100).eh_frame,
6833             func_base: None,
6834             address_size: 4,
6835             section: &input,
6836         };
6837         assert_eq!(
6838             parse_encoded_pointer(encoding, &parameters, &mut rest),
6839             Ok(Pointer::Direct(0x111))
6840         );
6841         assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
6842     }
6843 
6844     #[test]
test_parse_encoded_pointer_pcrel_undefined()6845     fn test_parse_encoded_pointer_pcrel_undefined() {
6846         let encoding = constants::DW_EH_PE_pcrel;
6847 
6848         let input = Section::with_endian(Endian::Little).L32(0x1);
6849         let input = input.get_contents().unwrap();
6850         let input = EndianSlice::new(&input, LittleEndian);
6851         let mut rest = input;
6852 
6853         let parameters = PointerEncodingParameters {
6854             bases: &SectionBaseAddresses::default(),
6855             func_base: None,
6856             address_size: 4,
6857             section: &input,
6858         };
6859         assert_eq!(
6860             parse_encoded_pointer(encoding, &parameters, &mut rest),
6861             Err(Error::PcRelativePointerButSectionBaseIsUndefined)
6862         );
6863     }
6864 
6865     #[test]
test_parse_encoded_pointer_textrel()6866     fn test_parse_encoded_pointer_textrel() {
6867         let encoding = constants::DW_EH_PE_textrel;
6868         let expected_rest = [1, 2, 3, 4];
6869 
6870         let input = Section::with_endian(Endian::Little)
6871             .L32(0x1)
6872             .append_bytes(&expected_rest);
6873         let input = input.get_contents().unwrap();
6874         let input = EndianSlice::new(&input, LittleEndian);
6875         let mut rest = input;
6876 
6877         let parameters = PointerEncodingParameters {
6878             bases: &BaseAddresses::default().set_text(0x10).eh_frame,
6879             func_base: None,
6880             address_size: 4,
6881             section: &input,
6882         };
6883         assert_eq!(
6884             parse_encoded_pointer(encoding, &parameters, &mut rest),
6885             Ok(Pointer::Direct(0x11))
6886         );
6887         assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
6888     }
6889 
6890     #[test]
test_parse_encoded_pointer_textrel_undefined()6891     fn test_parse_encoded_pointer_textrel_undefined() {
6892         let encoding = constants::DW_EH_PE_textrel;
6893 
6894         let input = Section::with_endian(Endian::Little).L32(0x1);
6895         let input = input.get_contents().unwrap();
6896         let input = EndianSlice::new(&input, LittleEndian);
6897         let mut rest = input;
6898 
6899         let parameters = PointerEncodingParameters {
6900             bases: &SectionBaseAddresses::default(),
6901             func_base: None,
6902             address_size: 4,
6903             section: &input,
6904         };
6905         assert_eq!(
6906             parse_encoded_pointer(encoding, &parameters, &mut rest),
6907             Err(Error::TextRelativePointerButTextBaseIsUndefined)
6908         );
6909     }
6910 
6911     #[test]
test_parse_encoded_pointer_datarel()6912     fn test_parse_encoded_pointer_datarel() {
6913         let encoding = constants::DW_EH_PE_datarel;
6914         let expected_rest = [1, 2, 3, 4];
6915 
6916         let input = Section::with_endian(Endian::Little)
6917             .L32(0x1)
6918             .append_bytes(&expected_rest);
6919         let input = input.get_contents().unwrap();
6920         let input = EndianSlice::new(&input, LittleEndian);
6921         let mut rest = input;
6922 
6923         let parameters = PointerEncodingParameters {
6924             bases: &BaseAddresses::default().set_got(0x10).eh_frame,
6925             func_base: None,
6926             address_size: 4,
6927             section: &input,
6928         };
6929         assert_eq!(
6930             parse_encoded_pointer(encoding, &parameters, &mut rest),
6931             Ok(Pointer::Direct(0x11))
6932         );
6933         assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
6934     }
6935 
6936     #[test]
test_parse_encoded_pointer_datarel_undefined()6937     fn test_parse_encoded_pointer_datarel_undefined() {
6938         let encoding = constants::DW_EH_PE_datarel;
6939 
6940         let input = Section::with_endian(Endian::Little).L32(0x1);
6941         let input = input.get_contents().unwrap();
6942         let input = EndianSlice::new(&input, LittleEndian);
6943         let mut rest = input;
6944 
6945         let parameters = PointerEncodingParameters {
6946             bases: &SectionBaseAddresses::default(),
6947             func_base: None,
6948             address_size: 4,
6949             section: &input,
6950         };
6951         assert_eq!(
6952             parse_encoded_pointer(encoding, &parameters, &mut rest),
6953             Err(Error::DataRelativePointerButDataBaseIsUndefined)
6954         );
6955     }
6956 
6957     #[test]
test_parse_encoded_pointer_funcrel()6958     fn test_parse_encoded_pointer_funcrel() {
6959         let encoding = constants::DW_EH_PE_funcrel;
6960         let expected_rest = [1, 2, 3, 4];
6961 
6962         let input = Section::with_endian(Endian::Little)
6963             .L32(0x1)
6964             .append_bytes(&expected_rest);
6965         let input = input.get_contents().unwrap();
6966         let input = EndianSlice::new(&input, LittleEndian);
6967         let mut rest = input;
6968 
6969         let parameters = PointerEncodingParameters {
6970             bases: &SectionBaseAddresses::default(),
6971             func_base: Some(0x10),
6972             address_size: 4,
6973             section: &input,
6974         };
6975         assert_eq!(
6976             parse_encoded_pointer(encoding, &parameters, &mut rest),
6977             Ok(Pointer::Direct(0x11))
6978         );
6979         assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
6980     }
6981 
6982     #[test]
test_parse_encoded_pointer_funcrel_undefined()6983     fn test_parse_encoded_pointer_funcrel_undefined() {
6984         let encoding = constants::DW_EH_PE_funcrel;
6985 
6986         let input = Section::with_endian(Endian::Little).L32(0x1);
6987         let input = input.get_contents().unwrap();
6988         let input = EndianSlice::new(&input, LittleEndian);
6989         let mut rest = input;
6990 
6991         let parameters = PointerEncodingParameters {
6992             bases: &SectionBaseAddresses::default(),
6993             func_base: None,
6994             address_size: 4,
6995             section: &input,
6996         };
6997         assert_eq!(
6998             parse_encoded_pointer(encoding, &parameters, &mut rest),
6999             Err(Error::FuncRelativePointerInBadContext)
7000         );
7001     }
7002 
7003     #[test]
test_parse_encoded_pointer_uleb128()7004     fn test_parse_encoded_pointer_uleb128() {
7005         let encoding =
7006             constants::DwEhPe(constants::DW_EH_PE_absptr.0 | constants::DW_EH_PE_uleb128.0);
7007         let expected_rest = [1, 2, 3, 4];
7008 
7009         let input = Section::with_endian(Endian::Little)
7010             .uleb(0x12_3456)
7011             .append_bytes(&expected_rest);
7012         let input = input.get_contents().unwrap();
7013         let input = EndianSlice::new(&input, LittleEndian);
7014         let mut rest = input;
7015 
7016         let parameters = PointerEncodingParameters {
7017             bases: &SectionBaseAddresses::default(),
7018             func_base: None,
7019             address_size: 4,
7020             section: &input,
7021         };
7022         assert_eq!(
7023             parse_encoded_pointer(encoding, &parameters, &mut rest),
7024             Ok(Pointer::Direct(0x12_3456))
7025         );
7026         assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7027     }
7028 
7029     #[test]
test_parse_encoded_pointer_udata2()7030     fn test_parse_encoded_pointer_udata2() {
7031         let encoding =
7032             constants::DwEhPe(constants::DW_EH_PE_absptr.0 | constants::DW_EH_PE_udata2.0);
7033         let expected_rest = [1, 2, 3, 4];
7034 
7035         let input = Section::with_endian(Endian::Little)
7036             .L16(0x1234)
7037             .append_bytes(&expected_rest);
7038         let input = input.get_contents().unwrap();
7039         let input = EndianSlice::new(&input, LittleEndian);
7040         let mut rest = input;
7041 
7042         let parameters = PointerEncodingParameters {
7043             bases: &SectionBaseAddresses::default(),
7044             func_base: None,
7045             address_size: 4,
7046             section: &input,
7047         };
7048         assert_eq!(
7049             parse_encoded_pointer(encoding, &parameters, &mut rest),
7050             Ok(Pointer::Direct(0x1234))
7051         );
7052         assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7053     }
7054 
7055     #[test]
test_parse_encoded_pointer_udata4()7056     fn test_parse_encoded_pointer_udata4() {
7057         let encoding =
7058             constants::DwEhPe(constants::DW_EH_PE_absptr.0 | constants::DW_EH_PE_udata4.0);
7059         let expected_rest = [1, 2, 3, 4];
7060 
7061         let input = Section::with_endian(Endian::Little)
7062             .L32(0x1234_5678)
7063             .append_bytes(&expected_rest);
7064         let input = input.get_contents().unwrap();
7065         let input = EndianSlice::new(&input, LittleEndian);
7066         let mut rest = input;
7067 
7068         let parameters = PointerEncodingParameters {
7069             bases: &SectionBaseAddresses::default(),
7070             func_base: None,
7071             address_size: 4,
7072             section: &input,
7073         };
7074         assert_eq!(
7075             parse_encoded_pointer(encoding, &parameters, &mut rest),
7076             Ok(Pointer::Direct(0x1234_5678))
7077         );
7078         assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7079     }
7080 
7081     #[test]
test_parse_encoded_pointer_udata8()7082     fn test_parse_encoded_pointer_udata8() {
7083         let encoding =
7084             constants::DwEhPe(constants::DW_EH_PE_absptr.0 | constants::DW_EH_PE_udata8.0);
7085         let expected_rest = [1, 2, 3, 4];
7086 
7087         let input = Section::with_endian(Endian::Little)
7088             .L64(0x1234_5678_1234_5678)
7089             .append_bytes(&expected_rest);
7090         let input = input.get_contents().unwrap();
7091         let input = EndianSlice::new(&input, LittleEndian);
7092         let mut rest = input;
7093 
7094         let parameters = PointerEncodingParameters {
7095             bases: &SectionBaseAddresses::default(),
7096             func_base: None,
7097             address_size: 4,
7098             section: &input,
7099         };
7100         assert_eq!(
7101             parse_encoded_pointer(encoding, &parameters, &mut rest),
7102             Ok(Pointer::Direct(0x1234_5678_1234_5678))
7103         );
7104         assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7105     }
7106 
7107     #[test]
test_parse_encoded_pointer_sleb128()7108     fn test_parse_encoded_pointer_sleb128() {
7109         let encoding =
7110             constants::DwEhPe(constants::DW_EH_PE_textrel.0 | constants::DW_EH_PE_sleb128.0);
7111         let expected_rest = [1, 2, 3, 4];
7112 
7113         let input = Section::with_endian(Endian::Little)
7114             .sleb(-0x1111)
7115             .append_bytes(&expected_rest);
7116         let input = input.get_contents().unwrap();
7117         let input = EndianSlice::new(&input, LittleEndian);
7118         let mut rest = input;
7119 
7120         let parameters = PointerEncodingParameters {
7121             bases: &BaseAddresses::default().set_text(0x1111_1111).eh_frame,
7122             func_base: None,
7123             address_size: 4,
7124             section: &input,
7125         };
7126         assert_eq!(
7127             parse_encoded_pointer(encoding, &parameters, &mut rest),
7128             Ok(Pointer::Direct(0x1111_0000))
7129         );
7130         assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7131     }
7132 
7133     #[test]
test_parse_encoded_pointer_sdata2()7134     fn test_parse_encoded_pointer_sdata2() {
7135         let encoding =
7136             constants::DwEhPe(constants::DW_EH_PE_absptr.0 | constants::DW_EH_PE_sdata2.0);
7137         let expected_rest = [1, 2, 3, 4];
7138         let expected = 0x111 as i16;
7139 
7140         let input = Section::with_endian(Endian::Little)
7141             .L16(expected as u16)
7142             .append_bytes(&expected_rest);
7143         let input = input.get_contents().unwrap();
7144         let input = EndianSlice::new(&input, LittleEndian);
7145         let mut rest = input;
7146 
7147         let parameters = PointerEncodingParameters {
7148             bases: &SectionBaseAddresses::default(),
7149             func_base: None,
7150             address_size: 4,
7151             section: &input,
7152         };
7153         assert_eq!(
7154             parse_encoded_pointer(encoding, &parameters, &mut rest),
7155             Ok(Pointer::Direct(expected as u64))
7156         );
7157         assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7158     }
7159 
7160     #[test]
test_parse_encoded_pointer_sdata4()7161     fn test_parse_encoded_pointer_sdata4() {
7162         let encoding =
7163             constants::DwEhPe(constants::DW_EH_PE_absptr.0 | constants::DW_EH_PE_sdata4.0);
7164         let expected_rest = [1, 2, 3, 4];
7165         let expected = 0x111_1111 as i32;
7166 
7167         let input = Section::with_endian(Endian::Little)
7168             .L32(expected as u32)
7169             .append_bytes(&expected_rest);
7170         let input = input.get_contents().unwrap();
7171         let input = EndianSlice::new(&input, LittleEndian);
7172         let mut rest = input;
7173 
7174         let parameters = PointerEncodingParameters {
7175             bases: &SectionBaseAddresses::default(),
7176             func_base: None,
7177             address_size: 4,
7178             section: &input,
7179         };
7180         assert_eq!(
7181             parse_encoded_pointer(encoding, &parameters, &mut rest),
7182             Ok(Pointer::Direct(expected as u64))
7183         );
7184         assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7185     }
7186 
7187     #[test]
test_parse_encoded_pointer_sdata8()7188     fn test_parse_encoded_pointer_sdata8() {
7189         let encoding =
7190             constants::DwEhPe(constants::DW_EH_PE_absptr.0 | constants::DW_EH_PE_sdata8.0);
7191         let expected_rest = [1, 2, 3, 4];
7192         let expected = -0x11_1111_1222_2222 as i64;
7193 
7194         let input = Section::with_endian(Endian::Little)
7195             .L64(expected as u64)
7196             .append_bytes(&expected_rest);
7197         let input = input.get_contents().unwrap();
7198         let input = EndianSlice::new(&input, LittleEndian);
7199         let mut rest = input;
7200 
7201         let parameters = PointerEncodingParameters {
7202             bases: &SectionBaseAddresses::default(),
7203             func_base: None,
7204             address_size: 4,
7205             section: &input,
7206         };
7207         assert_eq!(
7208             parse_encoded_pointer(encoding, &parameters, &mut rest),
7209             Ok(Pointer::Direct(expected as u64))
7210         );
7211         assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7212     }
7213 
7214     #[test]
test_parse_encoded_pointer_omit()7215     fn test_parse_encoded_pointer_omit() {
7216         let encoding = constants::DW_EH_PE_omit;
7217 
7218         let input = Section::with_endian(Endian::Little).L32(0x1);
7219         let input = input.get_contents().unwrap();
7220         let input = EndianSlice::new(&input, LittleEndian);
7221         let mut rest = input;
7222 
7223         let parameters = PointerEncodingParameters {
7224             bases: &SectionBaseAddresses::default(),
7225             func_base: None,
7226             address_size: 4,
7227             section: &input,
7228         };
7229         assert_eq!(
7230             parse_encoded_pointer(encoding, &parameters, &mut rest),
7231             Err(Error::CannotParseOmitPointerEncoding)
7232         );
7233         assert_eq!(rest, input);
7234     }
7235 
7236     #[test]
test_parse_encoded_pointer_bad_encoding()7237     fn test_parse_encoded_pointer_bad_encoding() {
7238         let encoding = constants::DwEhPe(constants::DW_EH_PE_sdata8.0 + 1);
7239 
7240         let input = Section::with_endian(Endian::Little).L32(0x1);
7241         let input = input.get_contents().unwrap();
7242         let input = EndianSlice::new(&input, LittleEndian);
7243         let mut rest = input;
7244 
7245         let parameters = PointerEncodingParameters {
7246             bases: &SectionBaseAddresses::default(),
7247             func_base: None,
7248             address_size: 4,
7249             section: &input,
7250         };
7251         assert_eq!(
7252             parse_encoded_pointer(encoding, &parameters, &mut rest),
7253             Err(Error::UnknownPointerEncoding)
7254         );
7255     }
7256 
7257     #[test]
test_parse_encoded_pointer_aligned()7258     fn test_parse_encoded_pointer_aligned() {
7259         // FIXME: support this encoding!
7260 
7261         let encoding = constants::DW_EH_PE_aligned;
7262 
7263         let input = Section::with_endian(Endian::Little).L32(0x1);
7264         let input = input.get_contents().unwrap();
7265         let input = EndianSlice::new(&input, LittleEndian);
7266         let mut rest = input;
7267 
7268         let parameters = PointerEncodingParameters {
7269             bases: &SectionBaseAddresses::default(),
7270             func_base: None,
7271             address_size: 4,
7272             section: &input,
7273         };
7274         assert_eq!(
7275             parse_encoded_pointer(encoding, &parameters, &mut rest),
7276             Err(Error::UnsupportedPointerEncoding)
7277         );
7278     }
7279 
7280     #[test]
test_parse_encoded_pointer_indirect()7281     fn test_parse_encoded_pointer_indirect() {
7282         let expected_rest = [1, 2, 3, 4];
7283         let encoding = constants::DW_EH_PE_indirect;
7284 
7285         let input = Section::with_endian(Endian::Little)
7286             .L32(0x1234_5678)
7287             .append_bytes(&expected_rest);
7288         let input = input.get_contents().unwrap();
7289         let input = EndianSlice::new(&input, LittleEndian);
7290         let mut rest = input;
7291 
7292         let parameters = PointerEncodingParameters {
7293             bases: &SectionBaseAddresses::default(),
7294             func_base: None,
7295             address_size: 4,
7296             section: &input,
7297         };
7298         assert_eq!(
7299             parse_encoded_pointer(encoding, &parameters, &mut rest),
7300             Ok(Pointer::Indirect(0x1234_5678))
7301         );
7302         assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
7303     }
7304 }
7305