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