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